The following code
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;
}
Gives me this error:
error: call to constructor of 'Bar<Baz>' is ambiguous
How can I fix this?
(Seems simple, I'm sure there's a duplicate somewhere, but I couldn't find it... all questions I found with "ambiguous constructor" stuff had to do with overloaded constructors, and this seems different to me.)
You have two constructors in Bar<Baz>
:
Bar(Baz& );
Bar(const Bar& );
The fact that the second is deleted doesn't matter for the purposes of overload resolution. You are trying to construct it from a Foo<Baz>&
... which is both a Baz
and a Bar<Baz>
, so both overloads apply - and the compiler can't prefer one over the other, so gives you the ambiguous error. Here's a simpler example with no templates that demonstrates the same issue:
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
}
To break the ambiguity, could just explicitly tell the compiler which overload to use with casting:
Foo(): Bar<T>(static_cast<T&>(*this)) {} // will call Bar(Baz&)
Deleted constructors participate in overload resolution. This is in order to ensure that the compilation really fails if a program attempts to use a deleted constructor. See this answer for more details.
The relevant section in the C++11 standard is 8.4.3/2:
A program that refers to a deleted function implicitly or explicitly, other than to declare it, is ill-formed.
[ Note: This includes calling the function implicitly or explicitly and forming a pointer or pointer-to-member to the function. It applies even for references in expressions that are not potentially-evaluated. If a function is overloaded, it is referenced only if the function is selected by overload resolution. —end note ]
You can solve your problem by making the constructor call unambiguous:
template<class T>
struct Foo: public T,
public Bar<T>
{
Foo(): Bar<T>(static_cast<T &>(*this)){}
};
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.