为什么返回 std::string 的 constexpr 函数在外部模板 class 时不编译?
Why doesn't constexpr function returning std::string doesn't compile when outside templated class?
注意:我使用的是 gcc,但在 godbolt.org 上测试过,它也适用于 msvc,但不适用于 clang
我无意中发现以下简单函数在模板化时可以编译 class,但不能作为自由函数编译。有人可以解释为什么吗?
编译成功:
template <typename T = void>
class A
{
public:
static constexpr std::string f()
{
return std::string();
}
}
不编译:
constexpr std::string f()
{
return std::string();
}
抛出错误:
error: invalid return type ‘std::string’ {aka ‘std::__cxx11::basic_string<char>’} of ‘constexpr’ function ...
...
/usr/include/c++/9/bits/basic_string.h:77:11: note: ‘std::__cxx11::basic_string<char>’ is not literal because:
77 | class basic_string
| ^~~~~~~~~~~~
/usr/include/c++/9/bits/basic_string.h:77:11: note: ‘std::__cxx11::basic_string<char>’ has a non-trivial destructor
std::string
应该是 C++20 中的文字类型。但是,GCC 似乎还没有实现这个新功能,所以它不能接受 std::string
作为 constexpr
函数的 return 类型。
但是,当 constexpr
函数是模板的一部分时,它在实例化之前不会作为函数存在。 class 模板是 class 的 蓝图 ;它本身不是 class。当 class 模板被实例化时, 然后 它的成员集就会产生。所以在你的第一个例子中,你有一个 class 模板,它 总是 产生格式错误的实例化,因为 A<T>::f
总是有一个无效的 return 类型。当这种情况发生时,程序是“ill-formed, no diagnostic required”,这意味着程序是错误格式的,但是编译器不需要告诉你程序是错误格式的。如果编译器接受程序,运行程序的结果是未定义的。
注意:我使用的是 gcc,但在 godbolt.org 上测试过,它也适用于 msvc,但不适用于 clang
我无意中发现以下简单函数在模板化时可以编译 class,但不能作为自由函数编译。有人可以解释为什么吗?
编译成功:
template <typename T = void>
class A
{
public:
static constexpr std::string f()
{
return std::string();
}
}
不编译:
constexpr std::string f()
{
return std::string();
}
抛出错误:
error: invalid return type ‘std::string’ {aka ‘std::__cxx11::basic_string<char>’} of ‘constexpr’ function ...
...
/usr/include/c++/9/bits/basic_string.h:77:11: note: ‘std::__cxx11::basic_string<char>’ is not literal because:
77 | class basic_string
| ^~~~~~~~~~~~
/usr/include/c++/9/bits/basic_string.h:77:11: note: ‘std::__cxx11::basic_string<char>’ has a non-trivial destructor
std::string
应该是 C++20 中的文字类型。但是,GCC 似乎还没有实现这个新功能,所以它不能接受 std::string
作为 constexpr
函数的 return 类型。
但是,当 constexpr
函数是模板的一部分时,它在实例化之前不会作为函数存在。 class 模板是 class 的 蓝图 ;它本身不是 class。当 class 模板被实例化时, 然后 它的成员集就会产生。所以在你的第一个例子中,你有一个 class 模板,它 总是 产生格式错误的实例化,因为 A<T>::f
总是有一个无效的 return 类型。当这种情况发生时,程序是“ill-formed, no diagnostic required”,这意味着程序是错误格式的,但是编译器不需要告诉你程序是错误格式的。如果编译器接受程序,运行程序的结果是未定义的。