c++ - T 是否必须是完整的类型才能在 `std::declval 中使用`?
问题描述
考虑这个例子(来自这里):
#include <type_traits>
#include <iostream>
template <typename U>
struct A {
};
struct B {
template <typename F = int>
A<F> f() { return A<F>{}; }
using default_return_type = decltype(std::declval<B>().f());
};
int main()
{
B::default_return_type x{};
std::cout << std::is_same< B::default_return_type, A<int>>::value;
}
它在 gcc9.2 上编译没有错误,但 gcc7.2 和 clang 10.0.0 抱怨B
不完整。Clangs错误是:
prog.cc:11:58: error: member access into incomplete type 'B'
using default_return_type = decltype(std::declval<B>().f());
^
prog.cc:7:8: note: definition of 'B' is not complete until the closing '}'
struct B {
^
prog.cc:16:8: error: no type named 'default_return_type' in 'B'
B::default_return_type x{};
~~~^
prog.cc:17:35: error: no member named 'default_return_type' in 'B'
std::cout << std::is_same< B::default_return_type, A<int>>::value;
~~~^
解决方案
错误的来源不是std::declval
,而是类成员访问不完整。
在2.5 年前合并CWG1836 的决议之前,该标准要求类在类成员访问表达式 ( ) 中是完整的。[expr.ref]/2 在 C++11 中:E1.E2
对于第一个选项(点),第一个表达式应具有完整的类类型。
对于第一个选项(点),第一个表达式应是具有完整类类型的泛左值。
alias-declaration
而一个类在其自身内部并不被认为是完整的member-specification
。
C++17 中的 [class.mem]/6:
}
在class-specifier结束时,类被视为完全定义的对象类型([basic.types])(或完整类型)。在类member-specification中,类在函数体、默认参数、noexcept-specifier和默认成员初始值设定项(包括嵌套类中的此类内容)中被认为是完整的。否则,它在其自己的类成员规范中被视为不完整。
推荐阅读
- ibm-watson - Passing Slack Native JSON from Watson Assistant Dialog as Response
- sql - Storing a range of months in an SQL table
- visual-studio-code - How to run multiple VS Code instances to use different identities for interacting with a remote git repository while working with Remote Containers?
- python - Installing python 3.6 on mac along with pip
- xamarin - Identitty4 Access Token from Android and token lenght
- node.js - I keep getting "Unexpected end of JSON input"
- c# - How to read the custom configuration settings in c#?
- vb.net - 如何使用 devexpress 根据某些列值更改行颜色?
- php - PHP string replace not working as expected
- c - Eclipse c 格式化程序 | 在函数头中保留 arg-type 和 arg-name 之间的空格