2014-10-26 1 views
1

Следующий кодвызова в шаблон базового конструктора неоднозначна

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

Удален Конструкторов участвовать в перегрузке разрешающая способность. Это делается для того, чтобы компиляция действительно терпит неудачу, если программа пытается использовать удаленный конструктор. См. this answer для более подробной информации.

Соответствующий раздел в стандарте C++ 11 является 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 ]

Вы можете решить вашу проблему, сделав вызов конструктора однозначный:

template<class T> 
struct Foo: public T, 
      public Bar<T> 
{ 
    Foo(): Bar<T>(static_cast<T &>(*this)){} 
}; 
+1

Ahh gotcha, спасибо! Наверное, я всегда уклонялся от явного кастинга, поэтому я даже не считал его XP, но это то, что мне нужно сделать! –

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&) 
+0

Интересного, я Бесполезный «Я понимаю, что компилятор не заботится об удалении ... есть ли способ обойти это и выполнить то, что я хочу? (сохраняя структуру, как у меня?) –

+0

@AlexWhitt Вы можете явно использовать ее ... вызвать конструктор с помощью 'static_cast (* this)'. – Barry

+0

Ahh Я думаю, это то, что мне нужно сделать, спасибо! (Я думаю, что @jogojapan едва избил вас до удара!) –

Смежные вопросы