【问题标题】:Template instantiation of templated class constructor模板化类构造函数的模板实例化
【发布时间】:2020-07-01 10:56:11
【问题描述】:

使用 clang++ 编译失败,谁能解释为什么? (这可以用 g++ 编译)

struct X
{
  template <typename T> X() {}
};

template X::X<int>();

int main() { return 1; }



instantiate.cc:7:13: error: qualified reference to 'X' is a constructor name rather than a type in this context
template X::X<int>();
            ^
instantiate.cc:7:14: error: expected unqualified-id
template X::X<int>();
             ^
2 errors generated.

【问题讨论】:

    标签: c++ templates clang++


    【解决方案1】:

    构造函数没有名字。 [class.ctor]/1 中说了很多。它们是使用类名定义的特殊成员。但他们自己却是无名的。虽然 C++ 允许我们通过使用类名在某些上下文中引用 c'tors,但这些是有限的。一般来说,我们不能命名一个c'tor。

    这就是问题所在。要显式指定模板参数,我们必须使用模板实体的名称。构造函数没有名称,因此我们无法明确指定它们的参数。

    这是 [temp.arg.explicit] 中注释的主题,总结了规范性文本的意图。

    7 [ 注意:因为显式模板参数列表遵循 函数模板名称,并且因为转换成员函数 模板和构造函数成员函数模板在没有调用的情况下 使用函数名,无法提供显式模板 这些函数模板的参数列表。 — 尾注 ]

    我们仍然可以实例化或专门化构造函数,但前提是不必显式指定模板参数(如果它们是可推导的,或者来自默认模板参数)。例如

    struct X
    {
      template <typename T> X(T) {}
    };
    
    template X::X(int); // This will work
    

    所以 Clang 拒绝你的代码并没有错。 GCC 可能会提供扩展。但最终,该标准并没有提供一种方法来显式地向构造函数模板提供模板参数。


    进一步挖掘,有CWG581,进一步确认 Clang 的行为是预期的行为。它似乎也进入了最新的标准修订版,对规范性文本进行了一些更改。

    【讨论】:

    • 可能值得一提的是,如果我们使用默认模板参数,我们实际上可以在不使用模板参数推导的情况下提供模板构造函数的显式实例化定义,这种技术可能会在类模板的构造函数,希望利用 SFINAE 来控制 ctor 重载;基本上制作ctors模板只是为了使类模板参数成为相应ctor中的依赖类型(例如:not okok)。
    • (当然,对于这种 SFINAE ctor 重载机制,我们更愿意使用类模板参数依赖继承,或者对于 C++20,约束表达式)
    • @dfri - 很有趣,在分析此类问题时,默认模板参数似乎总是让我忘记。谢谢,修改了相应的段落。
    • 我自己很少在 ctors 上使用它们,但可能会求助于用户定义的转换。函数,特别是使用 SFINAE 来避免 warning: conv.功能.. 当关联的模板参数T 已经是 const 时,将永远不会使用 'MyType' 警告,通过删除所述重载; example。我刚刚了解到,我们对约束表达式的依赖名称没有与将 SFINAE 应用于类模板成员时相同的限制,这使得 much nicer
    【解决方案2】:

    我认为 Clang 是正确的。即使 Gcc 允许,模板化的构造函数也根本无法使用。模板参数不能推导,也不能为构造函数模板显式指定模板参数。

    [temp.arg.explicit]/2

    在引用构造函数模板([class.ctor]、[class.qual])的特化时,不应指定模板参数。

    [temp.arg.explicit]/8

    [ 注意:因为显式模板参数列表跟在函数模板名之后,并且因为构造函数模板([class.ctor])的命名没有使用函数名([class.qual]),所以无法提供这些函数模板的显式模板参数列表。 ——尾注]

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-02-09
      • 1970-01-01
      • 1970-01-01
      • 2011-05-08
      • 2016-07-02
      • 2011-05-24
      • 1970-01-01
      相关资源
      最近更新 更多