Search code examples
c++templatestemplate-meta-programmingstatic-assert

Can I static assert that an entity is instantiation of a template class without enforcing any/all template arguments?


Maybe the question in the title is too generic, and it is generic because I'm curious about

But this generic question sprung from a concrete, less generic use case.

I initially wrote a function dealing with an array of 2 elements of class A:

auto /* return type is not relevant */ fun(std::array<A,2>& a) {
    // ... do things...
}

then I decided to extend the functionality to the case that a has 3 elements. Handling this by using a std::vector<A> is not an option as the two scenarios never interact with each other and I never need to push_back on/pop_back from a.

To make the two of them work together, I gave up on the explicit parameter type and relied on auto:

auto /* ditto */ fun(auto& a) {
    // ... do things, which depend on `auto` having deduced a `std::array<A,N>` for some `N`...
}

Doing so however is a bit undesirable because:

  • the code is less self-documenting than it could be: someone else (or myself in a month) would have to go look inside fun in order to undestand that it uses a assuming that it is a std::array<A,N> for a general N;
  • the error messages are less clear than they could be: the error would be along the lines of no function matches this call, whereas I'd like the error to be this function works with std::array of As.

What I could do, is keep auto and static_asserting in the first line of the function that a be std::array<A,2> or std::array<A,3>, but in the future I might want to handle the case 4 too.

So I'm just wandering if there's a way to assert that a variable a is instance of a given template class, e.g. std::array, with not all template parameters specified.

In general, given a tempalte class like this,

template<typename A, int n, typename B, int m>
class C { /* impl */ };

is it possible to assert that a variable a is of type C<some_class,some_number,?,?>?


Solution

  • Just make your function a template. N will be deduced automatically.

    template<std::size_t N>
    auto fun(std::array<A,N>& a) {
       // ... do things, which depend on `auto` having deduced a `std::array<A,N>` for some `N`...
    }