私は提供されたラムダを呼び出す関数を提供しようとしていますが、戻り値の型がvoid
の場合、デフォルト値を返すことができるかどうか疑問に思っています。C++ 11の戻り値と一致する方法はありますか?
は、ここでラムダの戻り値を返す関数は、私がこれまで持っているものだが、ラムダはvoid
であれば、それは
test.cpp:20:68: error: call of overloaded ‘f(main()::<lambda()>)’ is ambiguous
、これはエラーを生成します20.
#include <functional>
#include <iostream>
template <typename H>
auto f(H&& h) -> decltype(h(), void())
{
return h();
}
template <typename H>
auto f(H&& h) -> decltype(h(), int())
{
h();
return 20;
}
int main()
{
int r = f([](){ std::cout << "test1" << std::endl; return 10; }); // error here
std::cout << "r: " << r << std::endl;
r = f([](){ std::cout << "test2" << std::endl; });
std::cout << "r: " << r << std::endl;
return 0;
}
返します
これは明らかに、これはC++が戻り型に基づく多型を使用できないためです。しかし、decltype
のような良いC++ 11のトリックがあるのか、これを可能にするテンプレートマジックがあるのだろうかと疑問に思っています。コンパイラはvoid
の戻り値の型を推測して、int
またはvoid
のバージョンがf
であるかどうかはあいまいだと言っていますが、これはちょっとばかげているので、私は尋ねています。
f
関数が戻り値を期待しているが、ユーザーがreturn
文を含まないラムダを提供する場合、コンパイラはvoid
型を推測し、エラーを出力します。実際のシナリオでは、ユーザが提供する気にしていないときに合理的なデフォルトの戻り値がどれくらいあるべきかを知っているので、ユーザがしばしば不要なreturn
ステートメントを無視できるようにコンパイラを設定できるかどうか疑問に思っています便宜上
ありがとうございました。私はGCC 4.6.3を使用していることを言及する必要があります。
回答:
template <typename H>
auto f(H&& h) -> typename std::enable_if<std::is_same<decltype(h()), void>::value, int>::type
{
h();
return 20;
}
template <typename H>
auto f(H&& h) -> typename std::enable_if<std::is_same<decltype(h()), int>::value, int>::type
{
return h();
}
ありがとう:enable_if
を使用してのXEOの提案に基づいて、私が動作しているようです以下、思い付きました!
として、あなたが通常の機能にFをテストがありますか? – CharlesB
はい、通常の機能ではあいまいです。 – Steve
'decltype'の第2引数:何のために尋ねることはできますか? (本当に、わからないから!)。 – 0x499602D2