c++ - `decltype` 并将 ADL 查找与非 ADL 查找混合

标签 c++ c++11 decltype argument-dependent-lookup

<分区>

测试用例

让函数 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() {....} 声明可能没有帮助。

最佳答案

您可以使用详细命名空间和一些包装:

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); }

关于c++ - `decltype` 并将 ADL 查找与非 ADL 查找混合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19744324/

相关文章:

c++ - 为什么存在 decltype 时范围解析会失败?

c++ - C++获取返回值的类型

c++ - 将派生类推送到c++中基类的 vector

c++ - 带 & 的基于范围的 for 循环

c++ - c++11涉及类成员时如何使用auto return和decltype?

c++逐列构造矩阵读取列

c - 使用 C 中的 std::atomic

c++ - 使用 Maven NAR 插件对 ARM 进行交叉编译

java - 通过 JNI 传递、返回和转换为列表的 vector 列表

c++ - Boost上下文实现