结构类型和 contexpr 函数返回类型之间的区别

neb*_*uch 4 c++ non-type-template-parameter

我在玩 C++ 并对此感到困惑:

\n

cppreference.com表示非类型模板参数必须是结构类型,而文字类类型是结构类型的一个示例。然后它说\xe2\x80\x9cLiteral 类型是 constexpr 变量的类型,它们可以从 constexpr 函数\xe2\x80\x9d构造、操作和返回(强调我的)。(事实上​​, constexpr 函数的返回类型必须是文字类型。)

\n

所以我的理解是可以从 constexpr 函数返回暗示是文字类型暗示是结构类型暗示可以用作非类型模板参数。

\n

但它似乎std::optional 可以从 constexpr 函数返回(bar如下),但不能用作非类型模板参数(foo紧接如下)。这是怎么回事?

\n
#include <optional>\ntemplate <std::optional<int> Z> int foo(int x) { return x; }\nint main() { return foo<std::optional{0}>(0); }\n
Run Code Online (Sandbox Code Playgroud)\n

这会导致编译器错误(GCC 和 clang 分别)

\n
\n

<source>:2:30: 错误:\'std::Optional\' 不是模板非类型参数的有效类型,因为它不是结构性的

\n
\n
\n

<translation>:2:30: 错误:非类型模板参数的类型“std::Optional”不是结构类型

\n
\n

\n
#include <optional>\nconstexpr std::optional<int> bar() { return std::optional{0}; }\nint main() { return *bar(); }\n
Run Code Online (Sandbox Code Playgroud)\n

编译。

\n

Joh*_*nck 7

C++20 允许类作为非类型模板参数,如果它们满足以下条件

具有以下属性的文字类类型:

  • 所有基类和非静态数据成员都是公共且不可变的
  • 所有基类和非静态数据成员的类型都是结构类型或其(可能是多维)数组。

std::optional是文字类类型,但它具有非公共数据成员,因此不允许作为非类型模板参数。

您可以创建自己的optional类似类,仅包含公共数据成员,然后它将可用作模板参数。