模板化类构造函数的模板实例化

时间:2020-07-01 10:56:11

标签: c++ templates clang++

这不能用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.

2 个答案:

答案 0 :(得分:4)

构造函数没有名称。 [class.ctor]/1中已经说了很多。它们是使用类名定义的特殊成员。但是他们本身是无名的。尽管C ++允许我们通过使用类名在某些上下文中引用c'tor,但是这些限制是有限的。通常,我们不能命名c'tor。

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

这是[temp.arg.explicit]中注释的主题,该注释概述了规范文本的意图。

7 [注意:因为显式模板参数列表位于 函数模板名称,并且因为转换成员函数 模板和构造函数成员函数模板的调用不带 使用函数名称,无法提供显式模板 这些功能模板的参数列表。 —尾注]

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

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

template X::X(int); // This will work

因此Clang拒绝您的代码并没有错。 GCC可能会提供扩展。但是最终,该标准没有提供向构造函数模板显式提供模板参数的方法。


进一步研究时,发现CWG581,进一步确认了Clang的行为是预期的行为。通过对标准文本进行一些更改,它似乎也进入了最新的标准修订版。

答案 1 :(得分:2)

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

[temp.arg.explicit]/2

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

[temp.arg.explicit]/8

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