I have a lot of C++ classes that use the same list of template parameters
template<typename T, typename Index, typename Bool, typename Data, Index n_x, Index n_u, Index n_c, Index n_w>
class A {
...
};
template<typename T, typename Index, typename Bool, typename Data, Index n_x, Index n_u, Index n_c, Index n_w>
class B {
...
};
template<typename T, typename Index, typename Bool, typename Data, Index n_x, Index n_u, Index n_c, Index n_w>
class C {
...
};
You get the idea. Then I instantiate them like
A<T, Index, Bool, Data, n_x, n_u, n_c, n_w> a;
B<T, Index, Bool, Data, n_x, n_u, n_c, n_w> b;
C<T, Index, Bool, Data, n_x, n_u, n_c, n_w> c;
Is there a way to somehow create an alias for this bundle of template parameters so that I don't have to keep re-typing the argument list?
I have something like this in mind...
using Params = T, Index, Bool, Data, n_x, n_u, n_c, n_w;
A<Params> a;
B<Params> b;
C<Params> c;
I realize that I could create a separate class which just defines types, and use that. But I am wondering if there is a way of doing this without defining a new class.
EDIT
I do not want to use macros.
I also do not want to use defaults because that would require ensuring that the defaults are uniform across a bunch of files. I realize that I could define a new header of defaults and just include that in all of the files, but that just seems like bad programming.
Not exactly what you asked but not so different...
But require a little work.
You can solve with a struct, foo
, with a double layer of template management.
template <typename T, typename Index, typename Bool, typename Data,
Index I1, Index I2, Index I3, Index I4>
struct foo
{
template <template <typename, typename X, typename, typename, X, X, X, X>
class Cont>
using type = Cont<T, Index, Bool, Data, I1, I2, I3, I4>;
};
A first layer, the struct layer, with the types/values you want to fix (T, Index, Bool, Data, n_x, n_u, n_c, n_w
, in your example).
A second layer, the using
layer, with the variable template element (A
, B
and C
, in your example.
You can also add a using
alias foot_t
to simplify the use
template <template <typename, typename X, typename, typename, X, X, X, X>
class Cont, typename C>
using foo_t = typename C::template type<Cont>;
Now you can fix types and values (the first layer) with a using
using f = foo<T, Index, Bool, Data, n_x, n_u, n_c, n_w>;
and declare variable activating second layer using foo_t
foo_t<A, f> a;
foo_t<B, f> b;
foo_t<C, f> c;
The following is a full working example
#include <vector>
#include <iostream>
template <typename T, typename Index, typename Bool, typename Data,
Index n_x, Index n_u, Index n_c, Index n_w>
class A { };
template <typename T, typename Index, typename Bool, typename Data,
Index n_x, Index n_u, Index n_c, Index n_w>
class B { };
template <typename T, typename Index, typename Bool, typename Data,
Index n_x, Index n_u, Index n_c, Index n_w>
class C { };
template <typename T, typename Index, typename Bool, typename Data,
Index I1, Index I2, Index I3, Index I4>
struct foo
{
template <template <typename, typename X, typename, typename, X, X, X, X>
class Cont>
using type = Cont<T, Index, Bool, Data, I1, I2, I3, I4>;
};
template <template <typename, typename X, typename, typename, X, X, X, X>
class Cont, typename C>
using foo_t = typename C::template type<Cont>;
int main ()
{
using T = float;
using Index = std::size_t;
using Bool = bool;
using Data = std::vector<std::string>;
constexpr std::size_t n_x { 0U };
constexpr std::size_t n_u { 1U };
constexpr std::size_t n_c { 2U };
constexpr std::size_t n_w { 3U };
using f = foo<T, Index, Bool, Data, n_x, n_u, n_c, n_w>;
foo_t<A, f> a;
foo_t<B, f> b;
foo_t<C, f> c;
static_assert( std::is_same<decltype(a),
A<T, Index, Bool, Data, n_x, n_u, n_c, n_w>>{}, "!" );
static_assert( std::is_same<decltype(b),
B<T, Index, Bool, Data, n_x, n_u, n_c, n_w>>{}, "!" );
static_assert( std::is_same<decltype(c),
C<T, Index, Bool, Data, n_x, n_u, n_c, n_w>>{}, "!" );
}
You could replace the alias by a define, not perfect, but easy solution and it works.
#define PARAMS T, Index, Bool, Data, n_x, n_u, n_c, n_w
A<PARAMS> a;
B<PARAMS> b;
C<PARAMS> c;
Note: no ;
at the end of the define.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With