简体   繁体   English

调用模板基本构造函数不明确

[英]Call to template base constructor is ambiguous

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(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. 您正在尝试从Foo<Baz>& ...构造它,它既是Baz又是Bar<Baz> ,所以这两种重载都适用-编译器不能偏重于另一种,因此给您带来歧义错误。 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: 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 ] —尾注]

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)){}
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM