Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between structural type and type returned from contexpr function

I was playing with C++ and got confused by this:

cppreference.com says that a non-type template parameter must be a structural type and that a literal class type is an example of a structural type. Then it says that “Literal types are the types of constexpr variables and they can be constructed, manipulated, and returned from constexpr functions” (emphasis mine). (In fact the return type of a constexpr function must be a literal type.)

So my understanding was can be returned from constexpr function implies is a literal type implies is a structural type implies can be used as a non-type template parameter.

But it appears that std::optional can be returned from a constexpr function (bar below) but cannot be used as a non-type template parameter (foo immediately below). What's going on?

#include <optional>
template <std::optional<int> Z> int foo(int x) { return x; }
int main() { return foo<std::optional{0}>(0); }

This gives the compiler errors (GCC and clang resp.)

<source>:2:30: error: 'std::optional' is not a valid type for a template non-type parameter because it is not structural

<source>:2:30: error: type 'std::optional' of non-type template parameter is not a structural type

But

#include <optional>
constexpr std::optional<int> bar() { return std::optional{0}; }
int main() { return *bar(); }

compiles.

like image 989
nebuch Avatar asked Sep 07 '25 13:09

nebuch


1 Answers

C++20 allows classes as non-type template parameters if they are:

a literal class type with the following properties:

  • all base classes and non-static data members are public and non-mutable and
  • the types of all base classes and non-static data members are structural types or (possibly multi-dimensional) array thereof.

std::optional is a literal class type, but it has non-public data members, so is not allowed as a non-type template parameter.

You could make your own optional-like class with only public data members, then it would be usable as a template parameter.

like image 159
John Zwinck Avatar answered Sep 10 '25 06:09

John Zwinck