为什么返回 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”,这意味着程序是错误格式的,但是编译器不需要告诉你程序是错误格式的。如果编译器接受程序,运行程序的结果是未定义的。