【问题标题】:C++ - Invalid initialization of reference with template nested classC++ - 使用模板嵌套类的引用初始化无效
【发布时间】:2018-10-27 14:32:52
【问题描述】:

我们有两个模板类,Class1 有一个嵌套类。 Class2 需要从该嵌套类对象构造/转换。

template<typename T> struct Class1{    
    Class1() = default;
    class Inner{};
};

template<typename T> struct Class2{
    Class2() = default;
    template<typename T2> Class2(const Class1<T2>&) {}
    template<typename T2> Class2(const typename Class1<T2>::Inner&) {}
};

void foo(const Class2<int>&){}

...

Class1<int> c1;
Class1<int>::Inner i1;

foo( c1);
foo( i1); // <===================ERROR

错误文本是:

error: invalid initialization of reference of type ???const Class2<int>&??? from expression of type ???Class1<int>::Inner???

为什么会出现此错误?从Class1 构建有效。如果类不是模板,则从 Inner 构造也可以。

【问题讨论】:

    标签: c++ templates reference inner-classes


    【解决方案1】:

    没有办法调用第二个构造函数(采用Inner 的构造函数)。由于模板参数T2 出现在非推导上下文中,在命名依赖类型的范围解析运算符的左侧,必须明确指定。

    但是模板化构造函数的模板参数不能显式提供!必须推导出来。

    因此,第二个 c'tor 的替换总是失败。只有第一个 c'tor 使它重载决议。并且该重载决议看到您尝试将Class2&lt;int&gt;::Inner 对象绑定到const Class2&lt;int&gt;&amp;。该引用根本无法绑定。

    【讨论】:

    • 谢谢!我试图理解“非推断上下文”的概念。在这种情况下,编译器知道 i1 实际上是 Class1&lt;int&gt;::Inner 那么为什么它不能调用正确的构造函数呢?无论如何,没有解决方法来实现我想要的吗?
    • @AdyAdy - 编译器不能依赖该信息。你可以read more about it
    • 在该示例中,他们将函数称为g(double{})。我认为这是不同的,因为我不能打电话给foo(Inner{})。内部总是来自Class1&lt;some-type&gt;。我不想争论只是想了解它是如何工作的。
    • @AdyAdy - 这是肤浅的。需要注意的重要一点是,专业化的可能性意味着::Inner 可能不是人们所期望的。所以编译器可能不会推导出T2。我知道这是反直觉的。但是暂时忘记您的主要模板。想象一个写template&lt;&gt; struct Class1&lt;int&gt; { typedef void Inner; };的恶意用户。该语言允许用户这样做。所以编译器无法从Inner 中推断出任何东西。
    猜你喜欢
    • 2016-08-08
    • 2016-04-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-19
    • 1970-01-01
    • 1970-01-01
    • 2021-05-04
    相关资源
    最近更新 更多