使用用户定义的构造函数移动类型的构造,该构造函数接受使用不完整类型实例化的模板类型参数

问题描述 投票:0回答:1

试图理解为什么这段代码不能用 gcc 和 clang 编译,但可以用 msvc 编译。

编译器资源管理器

#include <type_traits>

class Incomplete;

template <class T>
struct Templated {
    T t;
};

struct Test {
    explicit Test(const Templated<Incomplete> &);
};

int main()
{
    static_assert(std::is_move_constructible_v<Test>, "Not move constructible");
}

海湾合作委员会错误:

<source>: In instantiation of 'struct Templated<Incomplete>':
/opt/compiler-explorer/gcc- 
13.2.0/include/c++/13.2.0/type_traits:3257:7:   required from 
'constexpr const bool std::is_move_constructible_v<Test>'
<source>:18:24:   required from here
<source>:9:7: error: 'Templated<T>::t' has incomplete type
    9 |     T t;
      |       ^
<source>:5:7: note: forward declaration of 'class Incomplete'
    5 | class Incomplete;
      |       ^~~~~~~~~~
Compiler returned: 1

Clang 错误在概念上是相同的。

如果删除

const
说明符或构造函数本身,代码将编译。尽管根本不应该使用构造函数,但为什么它会这样工作?

c++ gcc visual-c++ clang move-semantics
1个回答
0
投票

Templated<Incomplete>
可能有这样的构造函数:

Templated(Test&&);

如果是这样的话

Test unnamed(std::move(t));

,其中

t
Test
类型的变量,将是格式良好的。它将选择您的
Test
构造函数,并将
const Template<Incomplete>&
绑定到通过该构造函数构造的临时
Template<Incomplete>
对象。

那么

std::is_move_constructible_v<Test>
就是真的。

为了检查这种可能性,编译器必须实例化

Templated<Incomplete>

此实例化的格式不正确,因为

Templated<Incomplete>
具有在实例化时不完整的类型成员 (
Incomplete
)。

© www.soinside.com 2019 - 2024. All rights reserved.