不明确的可变参数类成员访问

Ambiguous variadic class member access

本文关键字:成员 访问 参数 变参 不明确      更新时间:2023-10-16

我刚刚开始我的更高级模板代码之旅。请考虑以下几点...

template <typename T>
class node_base
{
public:
    T member;
    node_base() {}
    void do_the_thing(node_base& other)
    {
        std::cout << other.member;
    }
};
template <typename ...Args>
class node : public node_base<Args>...
{
public:
    node() :node_base<Args>()...{}
};
int main()
{
    node<int> int_node;
    node<int, double> double_node;
    int_node.do_the_thing(double_node);
    double_node.do_the_thing(int_node); // ambiguous call
    std::cin.ignore();
    return 0;
}

使用Visual Studio 2017 15.4.5,我得到以下...

错误 C2385:"do_the_thing"的不明确访问 注意:可能是 基数"node_base"中的"do_the_thing"注意:或者可能是 基数"node_base"中的"do_the_thing">

我的理解是,编译器应该能够根据参数推断出正确的函数,在这种情况下node<int>。为什么这个电话被认为是模棱两可的?我可以做些什么来澄清调用,同时仍保持此模板模式?

这与模板无关。您可以使用以下内容重现它:

struct A1 { void foo(); };
struct A2 { void foo(); };
struct B : A1, A2 {};
int main()
{
    B b;
    b.foo();
}

该标准的相关部分是

如果生成的声明集并非全部来自同一类型的子对象,或者该集具有非静态成员并包含来自不同子对象的成员,则存在歧义,并且程序格式不正确。

因此,您有两个类型为 node_base<int>node_base<double> 的子对象。

编辑:为了解决问题的变化,并且由于DeanSeo删除了他的解决方案,我将在此处发布:

template <typename T>
class node_base
{
public:
    T member = sizeof(T);
    node_base() {}
    void do_the_thing(node_base& other) {
        std::cout << other.member << std::endl;
    }
};
template <typename ...Args>
class node : public node_base<Args>...
{
public:
    node() :node_base<Args>()...{}
    template <class T>
    void do_the_thing(node_base<T>& other) {
        node_base<T>::do_the_thing(other);
    }
};
int main()
{
    node<int> int_node;
    node<double, int> double_node;
    int_node.do_the_thing<int>(double_node);
    double_node.do_the_thing(int_node);
    double_node.do_the_thing<double>(double_node);
    double_node.do_the_thing<int>(double_node);
    return 0;
}