Ale*_*ink 9 c++ templates language-lawyer incomplete-type
下面的代码无法在gcc 7.3.0和clang 6.0.0上编译(但似乎在MSVC下编译正常):
#include <utility>
struct IncompleteType;
template<typename T>
struct Container {
T value;
};
using Uninstantiatable = Container<IncompleteType>;
auto foo() -> decltype(static_cast<Uninstantiatable const&>(std::declval<Uninstantiatable const&>())) {
throw 1;
}
Run Code Online (Sandbox Code Playgroud)
我得到的错误是这样的:
<source>:7:7: error: field has incomplete type 'IncompleteType'
T value;
^
<source>:12:24: note: in instantiation of template class 'Container<IncompleteType>' requested here
auto foo() -> decltype(static_cast<Uninstantiatable const&>(std::declval<Uninstantiatable const&>())) {
^
<source>:3:8: note: forward declaration of 'IncompleteType'
struct IncompleteType;
^
1 error generated.
Compiler returned: 1
Run Code Online (Sandbox Code Playgroud)
亲自尝试一下:https://godbolt.org/g/5AW37K
但是,如果我替换第10行,它就会编译
using Uninstantiatable = IncompleteType;
Run Code Online (Sandbox Code Playgroud)
就像提到的@ Jarod42一样,如果删除Container的定义,它会再次编译:http://godbolt.org/g/ue9iwC因此,如果定义了gcc和clang,它只会实例化模板类.
在这两种情况下,我只是试图将const-ref复制到const-ref,所以我希望无论类型是什么都能工作,如果类型本身不完整,这确实有效.标准是否指定在此处触发模板实例化,或者gcc和clang在其行为中是否不正确?
请注意,上面代码中的模式取自gcc的std :: is_constructible实现,并且当我尝试复制包含带有不完整类型参数的模板化类的const ref的元组时触发了错误,所以是的,这个在实践中发生.
如果您不实例化模板类,则不会出现错误。
拥有
using Uninstantiatable = IncompleteType;
Run Code Online (Sandbox Code Playgroud)
意味着您仅生成IncompleteType
. 在未定义类型上拥有引用或指针是可以的,因为编译器只需在此处为指针生成代码。但是如果你实例化你的类:
template<typename T>
struct Container {
T value;
};
Run Code Online (Sandbox Code Playgroud)
这里您需要 T 的定义,它不是指针或引用,而是类型本身,此处未定义。因此编译器无法生成实例,因为它对此一无所知。
拥有
decltype(static_cast<Uninstantiatable const&>)
Run Code Online (Sandbox Code Playgroud)
意味着您实例化了模板,这会导致错误。它与您只需要该语句中的引用无关。它与生成模板本身的实例有关,这是无法完成的,因为如上所述,那里的“T”是未知的。
归档时间: |
|
查看次数: |
237 次 |
最近记录: |