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

时间:2018-03-20 01:17:37

标签: c++ variadic-templates

我刚开始进入更高级的模板代码之旅。请考虑以下内容......

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:&#39; do_the_thing&#39;模糊访问注意:可能是   &#39; do_the_thing&#39;在base&#39; node_base&#39;注意:或者可能是   &#39; do_the_thing&#39;在base&#39; node_base&#39;

我的理解是编译器应该能够根据参数推导出正确的函数,在本例中为node<int>。为什么这个电话被认为是含糊不清的?在保持此模板模式的同时,我还能做些什么来澄清呼叫?

1 个答案:

答案 0 :(得分:2)

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

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