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?
There is no type for T that would allow the compiler to instantiate function template max<T> (T, T) into a function with two different parameter types. Put another way, because both parameters in the function template are of type T, they must resolve to the same actual type.
The best way to solve this problem is to rewrite our function template in such a way that our parameters can resolve to different types. Rather than using one template type parameter T, we’ll now use two (T and U):
This lack of type conversion is intentional for at least two reasons. First, it helps keep things simple: we either find an exact match between the function call arguments and template type parameters, or we don’t.
The return-type then follows at a point where parameter names can be used, i.e., after the -> is the return->type which is is normally in front of the function declaration. Put differently, if return-type does not refer to the names of arguments, the declaration above is equivalent to this declaration:
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
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