<分区>
测试用例
让函数 auto foo(T f)
的返回类型与从 header cmath
调用 sin(f)
时相同在 f
是内部数据类型的情况下:
template <typename T>
auto foo(T f) -> decltype(sin(f))
{
using std::sin;
return sin(f);
}
这个坏了。 decltype
中的 sin(f)
不会在 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
输出表明对于 foo->float
和 foo->double
,返回类型总是 double
>,只有 在 foo()
中,找到正确的 sin(float|double)
因为 using std::sin
,它导入所有重载。
我想知道 gremium 是否已经考虑过这种情况,但这不是我的问题。
问题
我的问题是:
什么是让 foo
具有与名称在 namespace std
或 ADL-looked-up 中的函数相同的返回类型的明智方法?
无效的解决方法:
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));
使用 enable_if
的排列是代码自文档化的方式。 enable_if
是一个很好的元编程练习。但是为了快速掌握一个看似简单的功能,恕我直言,这不是正确的事情,因此不符合可维护性。
编辑:我还使用 decltype
来减少对 SFINAE 的模糊使用,因此 C++14 及其新的 auto foo() {....}
声明可能没有帮助。