我刚开始进入更高级的模板代码之旅。请考虑以下内容......
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>
。为什么这个电话被认为是含糊不清的?在保持此模板模式的同时,我还能做些什么来澄清呼叫?
答案 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;
}