テストケース
が組み込みデータ型である場合、関数の戻り値の型をヘッダーからauto foo(T f)
呼び出す場合と同じにします。sin(f)
cmath
f
template <typename T>
auto foo(T f) -> decltype(sin(f))
{
using std::sin;
return sin(f);
}
これは壊れています。sin(f)
withinはwithindecltype
で検索されないため、戻り値の型が であるバリアントstd
のみが見つかります。次のプログラムは、次のことを示しています。C
sin(double)
double
#include <cmath>
#include <iostream>
#include <typeinfo>
namespace meh {
struct Nanometer {};
struct SinfulNanometer {};
SinfulNanometer sin(Nanometer) { return SinfulNanometer(); }
}
template <typename T>
auto foo(T f) -> decltype(sin(f))
{
using std::sin;
std::cout << typeid(decltype(sin(f))).name() << '\n';
}
int main () {
std::cout << typeid(decltype(foo(0.))).name() << '\n'
<< typeid(decltype(foo(0.f))).name() << '\n'
<< typeid(decltype(foo(meh::Nanometer()))).name() << '\n';
foo(0.);
foo(0.f);
foo(meh::Nanometer());
}
出力:
d
d
N3meh15SinfulNanometerE
d
f
N3meh15SinfulNanometerE
double
出力は、戻り値の型が常にfor foo->float
and foo->double
であることを 示唆していfoo()
ます。sin(float|double)
using std::sin
そのようなケースはすでに gremium で考慮されていたのだろうかと思いますが、それは私の質問ではありません。
質問
私の質問は:
名前が inまたは ADL-looked-up のfoo
いずれかである関数と同じ戻り値の型を持たせるための賢明な方法は何ですか?namespace std
機能しない回避策:
template <typename T>
auto foo(T f) -> decltype(std::sin(f)); // Will miss sin(Nanometer)
標準案?
template <typename T>
auto foo(T f) -> decltype(using std::sin; sin(f));
is の順列を使用するenable_if
と、コードの自己文書化が妨げられます。enable_if
メタプログラミングの良い練習です。しかし、一見単純な機能をすばやく把握することは、正しいことではないため、保守性の精神に反します。
編集:私はdecltype
SFINAEをあまりあいまいに使用することもしていないので、新しいauto foo() {....}
宣言を含むC++ 14は役に立たないかもしれません。