提供されたラムダを呼び出す関数を提供しようとしていますが、関数の戻り値がタイプの場合、デフォルト値を返すことができるかどうか疑問に思っていますvoid
。
これが私がこれまでに持っているものです。ラムダの戻り値を返す関数ですが、ラムダがの場合、void
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;
}
これにより、エラーが発生します。
test.cpp:20:68: error: call of overloaded ‘f(main()::<lambda()>)’ is ambiguous
したがって、これは明らかに、C++が戻り型に基づくポリモーフィズムを使用できないためです。decltype
ただし、これを可能にする可能性のある、C ++ 11の優れたトリック(テンプレートの魔法の使用法やテンプレートの魔法など)があるかどうか疑問に思っています。私が見る限り、ここには本当のあいまいさはないので、私は尋ねています。コンパイラは戻り型を推測し、またはのバージョンvoid
と一致するかどうかがあいまいであると言っています。これは少しばかげています。int
void
f
これを行う理由は、関数f
が戻り値を期待しているが、ユーザーがステートメントを含まないラムダを提供した場合return
、コンパイラーがvoid
型を推測し、エラーになるためです。実際のシナリオでは、ユーザーがデフォルトの戻り値を提供する必要がない場合に、適切なデフォルトの戻り値がどうあるべきかをよく理解しているので、コンパイラーでユーザーが頻繁に不要なreturn
ステートメントを無視できるようにすることができるかどうか疑問に思います。快適。
ありがとう。私はGCC4.6.3を使用していることに言及する必要があります。
回答:Xeoの使用の提案に基づいてenable_if
、私は次のことを思いつきました。これは機能しているようです。
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();
}
ありがとう!