以下代码
template<class T>
struct Bar
{
Bar(T& myT){}
Bar(const Bar&) = delete;
};
template<class T>
struct Foo: public T,
public Bar<T>
{
Foo(): Bar<T>(*this){}
};
class Baz{};
int main()
{
Foo<Baz> myFoo;
return 0;
}
给我这个错误:
error: call to constructor of 'Bar<Baz>' is ambiguous
我该如何解决这个问题?
(看起来很简单,我确定某处有重复,但我找不到它...我发现的所有“模糊构造函数”的问题都与重载的构造函数有关,这对我来说似乎有所不同。 )
答案 0 :(得分:0)
Bar<Baz>
中有两个构造函数:
Bar(Baz& );
Bar(const Bar& );
第二个被删除的事实对于重载解决的目的并不重要。您正在尝试从Foo<Baz>&
... Baz
和Bar<Baz>
构建它,因此两个重载都适用 - 并且编译器不能优先于其他,所以给你一个模棱两可的错误。这是一个更简单的示例,没有模板可以演示相同的问题:
struct A { };
struct B { };
struct C : A, B { };
void foo(A& ) { }
void foo(B& ) { }
int main() {
C c;
foo(c); // error: call of overloaded ‘foo(C&)’ is ambiguous
}
为了打破歧义,可以明确告诉编译器使用哪个重载:
Foo(): Bar<T>(static_cast<T&>(*this)) {} // will call Bar(Baz&)
答案 1 :(得分:0)
已删除的构造函数参与重载解析。这是为了确保在程序尝试使用已删除的构造函数时编译确实失败。有关详细信息,请参阅this answer。
C ++ 11标准中的相关部分是8.4.3 / 2:
除了声明它之外,隐式或显式引用已删除函数的程序是不正确的。
[注意:这包括隐式或显式调用函数并形成指针或指向成员的指针 到功能。它甚至适用于未进行潜在评估的表达式中的引用。如果一个功能 重载,只有在通过重载决策选择函数时才会引用它。 - 后注]
您可以通过使构造函数调用明确来解决您的问题:
template<class T>
struct Foo: public T,
public Bar<T>
{
Foo(): Bar<T>(static_cast<T &>(*this)){}
};