继承函数的重载解析

时间:2018-11-06 13:54:34

标签: c++ templates inheritance lambda overloading

我希望有一个结构,该结构可以容纳任意数量的lambda,并作为所有调用运算符的中央调用点。

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

我认为以下代码可以准确地完成此任务。通过Poc将每个lambda的调用运算符“提升”到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;
}

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

据我了解,lambda-call-operator和structs(默认)call-operator存在于同一作用域中。因此,应该全都考虑它们的过载分辨率。由于lamdba-operator比通用默认操作符更具体,因此应选择它。

显然不是这样。为什么会这样?

我在Microsoft Visual C++ClangGCC(均为最新版本)上进行了测试。

编辑:

1 个答案:

答案 0 :(得分:43)

发现它很简单:您的运算符没有const的资格,而the lambda's one是合格的(除非您将lambda定义为mutable)。因此,它更适合您的Poc的非常量实例。

只需添加丢失的const

auto operator() (Ts...) const