c++ - 为什么构造不完整类型的 std::unique_ptr 编译?

标签 c++ c++11 templates c++14 language-lawyer

代码:

#include <memory>

struct Data;
std::unique_ptr<Data> make_me();

int main()
{
    std::unique_ptr<Data> m = make_me();
    return 0;
}

当然失败了:

In file included from <source>:1:
In file included from /opt/compiler-explorer/gcc-7.1.0/lib/gcc/x86_64-linux-gnu/7.1.0/../../../../include/c++/7.1.0/memory:80:
/opt/compiler-explorer/gcc-7.1.0/include/c++/7.1.0/bits/unique_ptr.h:76:16: error: invalid application of 'sizeof' to an incomplete type 'Data'
        static_assert(sizeof(_Tp)>0,
                      ^~~~~~~~~~~
/opt/compiler-explorer/gcc-7.1.0/include/c++/7.1.0/bits/unique_ptr.h:268:4: note: in instantiation of member function 'std::default_delete<Data>::operator()' requested here
          get_deleter()(__ptr);
          ^
8 : <source>:8:31: note: in instantiation of member function 'std::unique_ptr<Data, std::default_delete<Data> >::~unique_ptr' requested here
    std::unique_ptr<Data> m = make_me();
                              ^
3 : <source>:3:8: note: forward declaration of 'Data'
struct Data;
       ^
1 error generated.
Compiler returned: 1

但在上述代码末尾添加以下行编译正常:

struct Data {};

我的问题是为什么当在 std::unique_ptr 实例化点之后声明数据时,这段代码可以编译和工作?看起来,这两种情况都应该失败并出现相同/相似的错误..

godbolt 上的完整示例:https://godbolt.org/g/FQqxwN

最佳答案

这是因为 point of instantiation template 的定义位于 Data 的定义之后。来自标准:

[temp.point]

For a class template specialization, a class member template specialization, or a specialization for a class member of a class template, if the specialization is implicitly instantiated because it is referenced from within another template specialization, if the context from which the specialization is referenced depends on a template parameter, and if the specialization is not instantiated previous to the instantiation of the enclosing template, the point of instantiation is immediately before the point of instantiation of the enclosing template. Otherwise, the point of instantiation for such a specialization immediately precedes the namespace scope declaration or definition that refers to the specialization.

A specialization for a function template, a member function template, or of a member function or static data member of a class template may have multiple points of instantiations within a translation unit, and in addition to the points of instantiation described above, for any such specialization that has a point of instantiation within the translation unit, the end of the translation unit is also considered a point of instantiation. A specialization for a class template has at most one point of instantiation within a translation unit. A specialization for any template may have points of instantiation in multiple translation units. If two different points of instantiation give a template specialization different meanings according to the one-definition rule, the program is ill-formed, no diagnostic required.

请注意,由于引用中的最后一句,这可能格式错误(NDR)。我没有足够的信心来判断这是否肯定是不正确的。

关于c++ - 为什么构造不完整类型的 std::unique_ptr 编译?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47928391/

相关文章:

c++ - & 在类型后的函数参数中

c++ - 对象没有命名类型 - C++

c++将模板与单例一起使用

c++ - 完美转发const ref扣减错误

c++ - snprintf() 返回不适当的值

c++ - 显示在 C++ 中创建临时文件的位置

c++ - 如何将枚举返回值转换为 C++ 异常?

c++ - 使用 STL 按成员(member)订购容器

c++ - 如何解压在 mixins 主机类中传递的一组元组(最终被转发给 mixins)

c++ - 使用推导类类型的占位符指定类型的非类型模板参数是否可以传递给 C++2a 中的另一个模板?