Search code examples
c++templatesc++17variadic

C++17: explicit first template parameter before variadic template


I am trying to write a generic class for a symmetric bloc matrix of arbitrary dimension. Only the upper triangular part is given:

A B C
  D E
    F

so the number of blocks is n*(n+1)/2 where n is the dimension (3 here).
A possible implementation with variadic templates is (I used integers for the blocks, for the sake of simplicity):

#include <tuple>
#include <cstddef>

template <size_t Dimension, typename... Blocks>
class SymmetricBlockMatrix {
public:
    constexpr SymmetricBlockMatrix(Blocks... blocks): blocks(blocks...) { }

    constexpr size_t dimension() const {
        return Dimension;
    }

protected:
    const std::tuple<Blocks...> blocks;
};

int main() {
    constexpr SymmetricBlockMatrix<3, int, int, int, int, int, int> m(1, 2, 3, 4, 5, 6);
    return 0;
}

I would of course check that the number of blocks is consistent with the dimension.

Is it somehow possible to provide only the dimension explicitly and let the compiler infer the types of the blocks? Then I could write:

int main() {
    constexpr SymmetricBlockMatrix<3> m(1, 2, 3, 4, 5, 6);
    return 0;
}

This results in the following compiler error:

error: no matching function for call to 'SymmetricBlockMatrix<3>::SymmetricBlockMatrix(int, int, int, int, int, int)'
   18 |     constexpr SymmetricBlockMatrix<3> m(1, 2, 3, 4, 5, 6);

Solution

  • One workaround is to use the old make helper function template trick along with auto as shown below:

    //this is a helper
    template <size_t V, typename... T>
    constexpr SymmetricBlockMatrix<V, T...> make_SymmetricBlockMatrix(T... t)
    {
        return SymmetricBlockMatrix<V, T...>{t...};
    }
    int main() {
        constexpr SymmetricBlockMatrix<3, int, int, int, int, int, int> k(1, 2, 3, 4, 5, 6);
        constexpr auto m = make_SymmetricBlockMatrix<3>(1, 2, 3, 4, 5, 6); //works now 
       
    }
    

    Working demo