我最近了解了不完整类型,在某些情况下它们可以用作模板参数。特别是,像void
,struct incomplete;
都是不完整类型。然后我编写了下面的程序,它可以与gcc一起工作,但不能与msvc和clang一起工作。Live demo
struct incomplete;
template<typename T> struct C
{
static constexpr T t{};
};
template<class T>
struct myClass {
C<T> new_t() { return {}; }
};
int main() {
myClass<incomplete> d;
d.new_t();
}
正如我们所看到的,上面的程序用gcc编译,而不是用msvc和clang编译。所以我想知道哪一个是正确的技术行为。
铿锵说道:
<source>:4:24: error: constexpr variable cannot have non-literal type 'const incomplete'
static constexpr T t{};
而MSVC说:
<source>(4): error C2027: use of undefined type 'incomplete'
<source>(1): note: see declaration of 'incomplete'
而愚者接受c17和c20的代码。
这里哪个编译器是正确的?
2条答案
按热度按时间bf1o4zei1#
程序格式错误并且 *gcc接受代码时出错 *,因为即使静态数据成员的定义未示例化(因为它不是odr使用的),它的声明仍将被示例化,这是由于
C<incomplete>
的 * 隐式示例化 * 按照temp.inst#3。更重要的是,如果声明使用constexpr
或inline
(C++17起)说明符,则成员必须声明为具有完整类型。来自温度指令#3:
类模板专用化的隐式示例化导致:
(强调我)
这意味着隐式示例化
C<incomplete>
将导致静态数据成员的声明的隐式示例化。从static data member documentation进一步:
但是,如果声明使用
constexpr
或inline
(C++17起)说明符,则成员必须声明为具有完整的类型。(强调我)
这意味着,由于隐式示例化声明声明了一个不完整类型的成员,因此该程序是格式错误的。
下面是gcc错误报告:
static constexpr incomplete (depedent) data member of a class template and in-member initialized incorrectly accepted
xa9qqrwz2#
根据[basic.def] 5.这是格式错误的:
在对象的定义中,该对象的类型不应是不完整类型([basic.types.general])、抽象类类型([class.abstract])或其数组(可能是多维数组)。
这似乎没有考虑到类模板的非odr使用成员。