John Boccio
John Boccio

Reputation: 35

How to use a struct declared with 'constexpr' as a template parameter?

Image you have a struct as follows:

struct DataParameters {
    int a;
    int b[2];
    int c;
};

In a specific situation, you know all these values at compile time:

constexpr DataParameters p = {
    .a = 5,
    .b = {3, 3},
    .c = 12
};

You then want to create a template function which uses the values of a, b, c. The following syntax is valid since the struct is declared as constexpr.

template<int A, int B_0, int B_1, int C>
void doSomething() {
    ...
}

doSomething<p.a, p.b[0], p.b[1], p.c>();

But let's say you have a struct that is much bigger and you do not want a giant list of template parameters. Is there any better way to it? I've tried the following, but get compiler errors:

template<const DataParameters& P>
void doSomething() {
    ...
}

doSomething<p>();

Any suggestions?

Upvotes: 2

Views: 1249

Answers (1)

bolov
bolov

Reputation: 75853

Since C++11 you can have template <const DataParameters& P> with objects that have static storage duration and either external or internal linkage.

Since C++17 you can have template <const DataParameters& P> with objects that have static storage duration (the linkage restriction was removed)

Since C++20 you can have template <DataParameters P> . The non-type parameter can be (since C++20):

  • 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 bases classes and non-static data members are structural types or (possibly multi-dimensional) array thereof.

https://en.cppreference.com/w/cpp/language/template_parameters

struct DataParameters // don't use C style typedef
{
    int a;
    int b[2];
    int c;
};

template <const DataParameters& x>
void foo() {}

constexpr DataParameters gp{};

void test_ref_global()
{
    foo<gp>(); // ok since C++11
}

void test_ref_local()
{
    static constexpr DataParameters p{};    
    foo<p>(); // ok since C++17
}

template <DataParameters x> // ok since C++20
void bar() {}

auto test_val()
{
    constexpr DataParameters p{};
    bar<p>(); // ok since C++20
}

Upvotes: 5

Related Questions