首页 > 解决方案 > 为什么在模板化类之外时返回 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

标签: c++templatesconstexprconstexpr-function

解决方案


std::string应该是 C++20 中的文字类型。但是,GCC 似乎还没有实现这个新特性,所以它不能接受std::string作为constexpr函数的返回类型。

但是,当constexpr函数是模板的一部分时,在实例化之前它不会作为函数存在。类模板是类的蓝图;它本身不是一个类。当类模板被实例化时,的成员集就会产生。所以在你的第一个例子中,你所拥有的是一个类模板,它总是会产生格式错误的实例化,因为A<T>::f总是有一个无效的返回类型。发生这种情况时,程序“格式错误,不需要诊断”,这意味着程序格式错误,但不需要编译器告诉您程序格式错误。如果编译器接受程序,则运行程序的结果是不确定的。


推荐阅读