Почему функция constexpr, возвращающая std::string, не компилируется вне шаблонного класса?
Примечание: я использую 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
1 ответ
предполагается, что это буквальный тип в C ++ 20. Однако похоже, что GCC еще не реализовал эту новую функцию, поэтому он не может принимать
std::string
как возвращаемый тип функции.
Однако когда
constexpr
функция является частью шаблона, она не существует как функция, пока не будет создана. Шаблон класса - это план класса; это не класс. Когда шаблон создается экземпляр класса, то множество ее членов будет в полной мере. Итак, в вашем первом примере у вас есть шаблон класса, который всегда будет создавать некорректно сформированные экземпляры, потому что
A<T>::f
всегда будет иметь недопустимый тип возврата. Когда это происходит, программа «плохо сформирована, диагностика не требуется», что означает, что программа плохо сформирована, но компилятор не обязан сообщать вам, что программа плохо сформирована. Если компилятор принимает программу, результат выполнения программы не определен.