简体   繁体   中英

How to use Nested static templated structs in c++17

What I am trying to achieve is to use a struct as a template parameter for another struct, without instantiation, so that it all happens at compile time. For example:

template<int v>
struct Container {
    static const int value = v;
};

template<Container a, Container b>
struct BiggerContainer {
    static const int value = a.v > b.v ? a.v : b.v;
};

int main() {
std::cout << BiggerContainer<Container<42>, Container<42>>::value << std::endl;

return 0;
}

The error I get with this code is the following:

./code.cpp: In function 'int main()':
./code.cpp:44:61: error: type/value mismatch at argument 1 in template parameter list for 'template<Container<...auto...> a, Container<...auto...> b> struct BiggerContainer'
   44 |     std::cout << BiggerContainer<Container<42>, Container<42>>::value << std::endl;
      |                                                             ^~
./code.cpp:44:61: note:   expected a constant of type 'Container<...auto...>', got 'Container<42>'
./code.cpp:44:61: error: type/value mismatch at argument 2 in template parameter list for 'template<Container<...auto...> a, Container<...auto...> b> struct BiggerContainer'
./code.cpp:44:61: note:   expected a constant of type 'Container<...auto...>', got 'Container<42>'

What am I getting wrong here? What exactly does this error mean what could I change to get at what I'm trying?

Thank you!

You might have:

template <int v>
struct Container {
    static const int value = v;
};
// template <int v> using Container = std::integral_constant<int, v>;

template <typename lhs, typename rhs>
struct Max
{
    static const int value = lhs::value > rhs::value ? lhs::value : rhs::value;
};

int main() {
    std::cout << Max<Container<42>, Container<42>>::value << std::endl;
}

In C++17 you cannot use a class or struct as a non-type template parameter. Non-type parameters have to be ints, pointers, enums, or references. This changes in C++20.

Specifically, the following declaration parameterizes BiggerContainer on values of structs, which is not possible.

template<Container a, Container b>
struct BiggerContainer

There are a few other problems with the code, but this is the main issue which will cause you to have to redesign things.

The problem is that in your template arguments for BiggerContainer , you need to specify the template arguments for Container ( template<Container, Container> doesn't have template arguments for Container ).

One alternative is to use a template function, like this:

template<int v1, int v2>
int BiggerContainer(Container<v1> a, Container<v2> b)
{
    return a.value > b.value ? a.value : b.value;
}

Then calling it like:

BiggerContainer(Container<42>(), Container<42>()); // No need to add '::value'

NOTE: Must call constructer, Container<val>() not just a type Container<val> . (Because we're passing a value, not a type)

The problem with that solution is that it returns an int (value type), not a Container , but it may be okay for some uses.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM