在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)
内的decltype
未在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
和 foo->float
的返回类型始终为foo->double
, {{1}内只有 },由于foo()
导致了所有重载,因此找到了正确的sin(float|double)
。
我想知道这种情况是否已经考虑过了,但这不是我的问题。
我的问题是:
让using std::sin
具有与名称在foo
或ADL-looking-up中的函数相同的返回类型的合理方法是什么?
非工作解决方法:
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));
的排列阻碍了代码自我记录。 enable_if
是一个很好的元编程练习。但是为了快速掌握一个看似简单的功能,我认为这不是正确的,因此不符合可维护性的精神。
编辑:我也使用enable_if
使用SFINAE不那么模糊,因此带有新decltype
声明的C ++ 14可能没有帮助。
答案 0 :(得分:9)
您可以使用详细命名空间和一些包装:
namespace detail {
using std::sin;
template<typename T>
auto foo(T f) -> decltype(sin(f)) { return sin(f); }
}
template<typename T>
auto foo(T f) -> decltype(detail::foo(f)) { return detail::foo(f); }
答案 1 :(得分:7)
您需要一个级别的间接:
namespace find_sin
{
using std::sin;
template<typename T>
using type = decltype(sin(std::declval<T>()));
}
template <typename T>
find_sin::type<T> foo(T f)
{
// ...
}