对模板基础构造函数的调用是不明确的

时间:2014-10-26 02:31:55

标签: c++ templates constructor

以下代码

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

我该如何解决这个问题?

(看起来很简单,我确定某处有重复,但我找不到它...我发现的所有“模糊构造函数”的问题都与重载的构造函数有关,这对我来说似乎有所不同。 )

2 个答案:

答案 0 :(得分:0)

Bar<Baz>中有两个构造函数:

Bar(Baz& );
Bar(const Bar& );

第二个被删除的事实对于重载解决的目的并不重要。您正在尝试从Foo<Baz>& ... BazBar<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)){}
};