Reputation: 7367
I have some C++ classes that all have the same template parameters
template <typename T, size_t i>
struct A {
};
template <typename T, size_t i>
struct B : A<T,i>{
};
template <typename T, size_t i>
struct C : A<T,i>{
};
and so on. I also have a series of methods that will work on any of these classes. However, the problem is in the return type. I would like this method to return an instance of the passed in class, with the integer decremented by one. For instance, if I just overload the function, that would look like this
template <typename T, size_t i>
A<T,i-1> func(const A<T,i> & a){
}
template <typename T, size_t i>
B<T,i-1> func(const B<T,i> & a){
}
template <typename T, size_t i>
C<T,i-1> func(const C<T,i> & a){
}
Is there a way to accomplish this without overloading the function for each type? By that I mean... is it possible to replace these with a single templated function? The logic is identical for all of the functions.
I imagine that that would look something like
template <typename P, size_t i>
P<i-1> func( const P<i> & p ){
}
where P
somehow captures the original type A
, B
, or C
, as well as the inner type T
.
Or, if you think CRTP is the way to go, then how would I structure that?
Upvotes: 5
Views: 303
Reputation: 4258
I don't normally use the template template syntax. In case template type definitions are recursive, I'd rather stick with the old school way:
template<typename T, int I>
struct A{
using Other=A<T,I-1>;
};
template<typename P>
typename P::Other f(P);
Upvotes: 0
Reputation: 29032
It sounds like you need to use a template template parameter. These template parameters are themselves class templates. In the following example, P
is a template parameter which expects a class template where that class template expects a type argument followed by a size_t
argument (such as the class templates A
, B
or C
you provided):
template<template<class, size_t> class P, class T, size_t i>
P<T, i - 1> my_func(const P<T, i> & my_P);
int main()
{
A<int, 10> a;
B<char, 3> b;
C<double, 7> c;
auto smaller_a = my_func(a); // is a A<int, 9>
auto smaller_b = my_func(b); // is a B<char, 2>
auto smaller_c = my_func(c); // is a C<double, 6>
}
Since you did not explain what your function should actually do, I've just provided the function declaration and left out the definition.
C++11 compilation demonstration : https://godbolt.org/g/zpXVEb
Upvotes: 8