c++ - 为什么在模板化类之外时返回 std::string 的 constexpr 函数不能编译?
问题描述
注意:我使用的是 gcc,但在 godbolt.org 上进行了测试,它也适用于 msvc,但不适用于 clang
我偶然发现以下简单函数在模板类中编译,但不是作为自由函数。有人可以解释为什么吗?
编译正常:
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
函数的返回类型。
但是,当constexpr
函数是模板的一部分时,在实例化之前它不会作为函数存在。类模板是类的蓝图;它本身不是一个类。当类模板被实例化时,它的成员集就会产生。所以在你的第一个例子中,你所拥有的是一个类模板,它总是会产生格式错误的实例化,因为A<T>::f
总是有一个无效的返回类型。发生这种情况时,程序“格式错误,不需要诊断”,这意味着程序格式错误,但不需要编译器告诉您程序格式错误。如果编译器接受程序,则运行程序的结果是不确定的。