c++ 不完整类型可用于gcc,但不能用于clang和msvc

7xzttuei  于 2022-12-05  发布在  其他
关注(0)|答案(2)|浏览(133)

我最近了解了不完整类型,在某些情况下它们可以用作模板参数。特别是,像voidstruct 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的代码。
这里哪个编译器是正确的?

bf1o4zei

bf1o4zei1#

程序格式错误并且 *gcc接受代码时出错 *,因为即使静态数据成员的定义未示例化(因为它不是odr使用的),它的声明仍将被示例化,这是由于C<incomplete>的 * 隐式示例化 * 按照temp.inst#3。更重要的是,如果声明使用constexprinline(C++17起)说明符,则成员必须声明为具有完整类型。
来自温度指令#3:
类模板专用化的隐式示例化导致:

      • 未删除的类成员函数、成员类、作用域成员枚举、静态数据成员、成员模板和朋友的**声明的隐式示例化,而不是定义的隐式示例化;和

(强调我)
这意味着隐式示例化C<incomplete>将导致静态数据成员的声明的隐式示例化。
static data member documentation进一步:
但是,如果声明使用constexprinline(C++17起)说明符,则成员必须声明为具有完整的类型
(强调我)
这意味着,由于隐式示例化声明声明了一个不完整类型的成员,因此该程序是格式错误的。
下面是gcc错误报告:
static constexpr incomplete (depedent) data member of a class template and in-member initialized incorrectly accepted

xa9qqrwz

xa9qqrwz2#

根据[basic.def] 5.这是格式错误的:
在对象的定义中,该对象的类型不应是不完整类型([basic.types.general])、抽象类类型([class.abstract])或其数组(可能是多维数组)。
这似乎没有考虑到类模板的非odr使用成员。

相关问题