2017-12-25 7 views
4

msvcを最新のもの(25DEC17現在)。自分自身を返す関数をコード化してオーバーロードする方法は? C++ 17

template< typename T> 
    auto out_ (const T & val_) 
    { 
     // do something with val_ 

     // error: can not deduce auto from out_ 
     return out_; 
    } 

質問は、この小さな「もの」の上にいくつかの過負荷をコード化して書き込む方法です。

はい、msvcとC++ 17である必要があります。これはGCC 7.0.2ではコンパイルされません。 clangはまだ試していません。

おそらくファンクタのパターンは役に立ちますか?

助言してください...

+4

[型付きラムダ計算(https://en.wikipedia.org/wiki/Typed_lambda_calculus)自体を返す関数は、入力が困難(または不可能)です。したがって**関数はそれ自身を返すべきではありません**(それはC++に特有ではなく、Ocaml、Haskellなどでも失敗します)。数学的には、セットはそのパワーセットにはなりません([ZFC](https://en.wikipedia.org/wiki/Zermelo%E2%80%93Fraenkel_set_theory))。 IMHO、あなたのコードは理にかなっていません。 –

+1

あなたは解決しようとしている問題は何ですか? – Barry

答えて

0

テンプレートを忘れてしまいました。私は、ラムダがファンクタとして実装されているとして、この作品驚いていないよ

#include <iostream> 

    auto out_ = [] (auto & val_) 
    { 
     std::cout << val_; 
     return out_ ; 
    }; 

    int main() 
    { 
    out_("Hello ")("from ")("GCC ")(__VERSION__)(" !"); 
    // GCC can not compile this: (std::endl); 
    } 

:回答は、オートの+ラムダです。なぜGCC 7.0.2がstd :: endlを取ることができないのですか、今私は解読する時間がありません。

のstdとして

http://coliru.stacked-crooked.com/a/b85b5f89047b5828

:: ENDL「問題」とmax66ソリューション@私はC++ 20には、「自動」、「自動」を意味しますより良いテンプレート/ジェネリックラムダを持っていることと思います...

私のjQueryの仕事に集中しながら、私はこのコンセプトを発明したかもしれませんが、私はそれを「コールストリーム」と呼んでいます。それについての記事はほとんどありません。

しかし、(C++ 11以前の)実装は@ max66の解決策と非常によく似ていました。 C++ 17では、この単純な単一ラムダ(私の答えでは)をかなりエレガントなソリューションにしています。私はあえて記述します。

私はあなたのラムダソリューションは、G ++で動作することを驚いている

https://dbj.org/callstream-project-euler/

+0

"テンプレートを忘れる" - 正確ではない...ラムダ関数の 'auto'パラメータは、ラムダを' generic lambda 'で変換します。これは、テンプレート 'operator()'を持つ無名の構造体です。言い換えれば、 'auto&val_'は' T'がテンプレート型である 'T&val_'の構文的砂糖です。 – max66

+0

@ max66あなたの時間と努力のために多くのおかげです。 "テンプレートを忘れて"私はそれらを忘れて、コードを書くことを意味しました...しかし、彼らは1つのレベルのベローズであることに注意してください... –

2

...私はここに私のブログへのリンクを提供することがOKになるかどうかわからないです。打ち鳴らす++苦情が

error: variable 'out_' declared with deduced type 'auto' cannot appear in its own initializer 
return out_ ; 
     ^

と私はあなたのコードを拒否右打ち鳴らす++(と間違ったG ++、それを受け入れる)ですが、私はわからないと思います。

とにかく、ラムダ自体が興味深いという考えがあります。

オブジェクトに参照を返すテンプレートoperator()を持つ構造体に基づいて、非ラムダ(ただし、標準に準拠し、移植性があることを望みます)ソリューションを提案します。

私は、あなたは一例で、std::endl

outS{}("Hello ")("from ")("GCC ")(__VERSION__)(" !"); 

問題は異なるもので、書くことができ

struct outS 
{ 
    template <typename T> 
    outS const & operator() (T const & t) const 
    { 
     std::cout << t; 

     return *this; 
    } 
}; 

を意味します。

問題が定義されているstd::endl

template< class CharT, class Traits > 
std::basic_ostream<CharT, Traits>& endl(std::basic_ostream<CharT, Traits>& os); 

として(CPP Reference参照)ことで、std::endlはテンプレート関数です。オペレータはstd::endlの特定のバージョンを選択し<<ので

あなたは

std::cout << std::endl; 

または

std::wcout << std::endl; 

を書くことができます。

outS{}(std::endl); 

を次のようにoutSstd::endlの特定のバージョンを選択することはできませんので、しかし、あなたはoutSにそれを渡すことはできません。

したがって、明示的に指定する必要があります。 std::endlstd::coutと一致させるには、std::endlのテンプレートパラメータはcharstd::char_traits<char>です。

だから、あなたは(私が知っている、醜い)書くことができます

outS{}(std::endl<char, std::char_traits<char>>); 

しかし、あなたがstructベースのソリューション(outS)を実装している場合、あなたはとてもあなたが書くことができendl()方法

outS const & endl() const 
{ 
    std::cout << std::endl; 

    return *this; 
} 

を追加することができます

outS{}.endl(); 

以下は、 Gの例で

#include <iostream> 

struct outS 
{ 
    template <typename T> 
    outS const & operator() (T const & t) const 
    { 
     std::cout << t; 

     return *this; 
    } 

    outS const & endl() const 
    { 
     std::cout << std::endl; 

     return *this; 
    } 

}; 

int main() 
{ 
    outS{}("Hello ")("from ")("GCC ")(__VERSION__)(" !").endl(); 
} 
+0

なぜこの答えのほとんどは 'cout'と' endl'についてですか? – Barry

+0

@Barry - たぶん正しいものではないかもしれませんが、この答えは、OPの答えに答えてもらえます(主に...)。なぜなら、「out_」の使用を示し、「GCC 7.0.2の理由std :: endlを取らない、今すぐ私は解読する時間がない "。 – max66

+0

バランスの取れた関与のために多くのthaks @ max66。あなたの分析は明快です。 –

関連する問題