Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Auto non-type template parameter with user defined types

In this video at 27:35 Bryce Lelbach gives the following example:

template<auto... Dims>
struct dimensions {};

struct dynamic_extent {};
constexpr dynamic_extent dyn = {};

dimensions<64, dyn, 32> d;

This code does not compile. GCC complains:

<source>:8:27: error: 'struct dynamic_extent' is not a valid type for a template non-type parameter
     dimensions<64, dyn, 32> d;
                           ^

Clang complains:

<source>:8:20: error: a non-type template parameter cannot have type 'dynamic_extent'
    dimensions<64, dyn, 32> d;
                   ^
<source>:2:22: note: template parameter is declared here
    template<auto... Dims>
                     ^

Is his example simply wrong (that's strange because he refers to a library where this idea is used) or I do not get something?

like image 758
Evg Avatar asked Jun 21 '18 18:06

Evg


2 Answers

Yes, his example is wrong.

Non-type template parameters cannot have class type until P0732, which is a C++20 feature. And even in C++20, this would still be ill-formed because in order to opt-in to use dyn as a non-type template parameter, you need:

struct dynamic_extent {
    auto operator<=>(dynamic_extent ) = default;
};

At that point, it'll work.


I assume what he meant was:

dimensions<64, &dyn, 32> d;
//             ^^^^

Passing that pointer is fine - pointers are acceptable non-type template parameters in C++17 (and way earlier), as long as they meet some other requirements - which dyn does.

like image 197
Barry Avatar answered Oct 19 '22 23:10

Barry


That example is wrong. This does not work in C++17. Non-type template parameters must be one of:

  • std::nullptr_t
  • integral type
  • lvalue reference type (to object or to function)
  • pointer type (to object or to function)
  • pointer to member type (to member object or to member function)
  • enumeration type

Arbitrary class types are not in this list.


Note that it would work to use an enum as the tag type:

template<auto... Dims>
struct dimensions {};

enum class dynamic_extent {};
constexpr dynamic_extent dyn = {};

dimensions<64, dyn, 32> d;
like image 25
Justin Avatar answered Oct 20 '22 01:10

Justin