【发布时间】:2013-11-02 16:51:08
【问题描述】:
测试用例
如果f 是一个内在数据类型,让函数auto foo(T f) 的返回类型与从标头cmath 调用sin(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 的返回类型始终为double 和 foo->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() {....} 声明可能没有帮助。
【问题讨论】:
-
在 C++14 中,您将能够只使用
auto;不需要decltype。 -
@rightfold:这也可以作为 SFINAE 的替代品吗?现在,我也在使用
decltype进行 SFINAE 技术。 -
我对这里的 SFINAE 不太确定。
-
@R.MartinhoFernandes:我想知道投票结束自己的问题是否值得徽章,因为我刚刚做到了:P
标签: c++ c++11 decltype argument-dependent-lookup