【问题标题】:Call to template base constructor is ambiguous对模板基构造函数的调用不明确
【发布时间】:2014-10-26 02:31:54
【问题描述】:

以下代码

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

我该如何解决这个问题?

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

【问题讨论】:

    标签: c++ templates constructor


    【解决方案1】:

    已删除的构造函数参与重载决议。这是为了确保在程序尝试使用已删除的构造函数时编译确实失败。详情请见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)){}
    };
    

    【讨论】:

    • 啊,明白了,谢谢!我想我一直回避这样的显式转换,所以我什至没有考虑过 XP,但这就是我必须做的!
    【解决方案2】:

    Bar&lt;Baz&gt; 中有两个构造函数:

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

    第二个被删除的事实对于重载解决方案并不重要。您正在尝试从 Foo&lt;Baz&gt;&amp;... 构建它.这是一个更简单的示例,没有演示相同问题的模板:

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

    【讨论】:

    • 有趣,我没有意识到编译器不会关心删除...有没有办法解决这个问题并且仍然完成我想要的? (保持结构不变?)
    • @AlexWhitt 你可以显式地转换它...用static_cast&lt;T&amp;&gt;(*this)调用构造函数。
    • 啊,我想这就是我必须做的,谢谢! (我认为@jogojapan 几乎没有击败你!)
    猜你喜欢
    • 1970-01-01
    • 2017-08-27
    • 2017-09-12
    • 1970-01-01
    • 2021-04-20
    • 2019-03-14
    • 1970-01-01
    • 2014-02-05
    • 1970-01-01
    相关资源
    最近更新 更多