小编Lcd*_*Drm的帖子

继承函数的重载分辨率

我希望有一个结构,它接受任意数量的lambda,并作为所有调用运算符的中心调用点.

如果使用与构造中给出的任何lambda都不匹配的参数列表调用调用运算符,则应调用默认调用运算符.

我认为以下代码将完成这一点.每个lambda的调用操作符都被"提升"到Poc类中using.

template <typename ...Lambdas>
struct Poc : Lambdas...
{
    using Lambdas::operator() ...; // Lift the lambda operators into the class

    template <typename ...Ts>
    auto operator() (Ts...)
    {
        std::cout << "general call" << std::endl;
    }
};

// Deduction guide
template <typename ...Ts>
Poc(Ts... ts)->Poc<Ts...>;

int main()
{
    auto l_int = [](int) {std::cout << "int" << std::endl; };

    Poc poc{l_int};
    poc(1);//calls the default operator. why?

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

当我在结构中没有默认的调用操作符时,一切都按预期工作(使用有效的参数列表).如果我将它添加到结构中(如上面的代码中所示),每次调用默认运算符,无论我调用哪个参数.

根据我的理解,lambda-call-operators和structs(默认)call-operator存在于同一范围内.因此,他们都应该考虑重载决议.由于lamdba运算符比通用默认运算符更具体,因此应该选择它.

显然事实并非如此.这是为什么?

我测试了Microsoft Visual C++, …

c++ lambda inheritance templates overloading

56
推荐指数
1
解决办法
1168
查看次数

查看命名空间的重载决策

以下代码按预期失败,因为没有get找到重载.使用std::get会解决问题.

#include <array>

int main()
{
    std::array<int, 2> ar{2,3};
    auto r = get<0>(ar);//fails, get was not declared in this scope
}
Run Code Online (Sandbox Code Playgroud)

但是,引入模板化的版本get,即使它不匹配函数调用,也会使编译器使用以下std::get版本:

#include <array>

template <typename T>
void get(){};

int main()
{
    std::array<int, 2> ar{2,3};

    auto r = get<0>(ar);//returns 2
}
Run Code Online (Sandbox Code Playgroud)

我找不到解释这一点的标准的任何部分.这是我测试的所有3个编译器中的错误(可能不是),或者我错过了什么?

此行为已在测试中

  • MSVC 15.9.2
  • Clang 8.0.0
  • GCC 9.0.0(仍为实验版)

编辑:我知道ADL.但是,如果ADL使第二个代码工作,为什么它不在第一部分?

c++ overload-resolution

34
推荐指数
2
解决办法
688
查看次数