Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

function return type with a different template parameter

Tags:

c++

c++11

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?

like image 422
bremen_matt Avatar asked May 07 '18 14:05

bremen_matt


People also ask

Is it possible to have two different parameter types for T?

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.

How can I resolve a template type parameter with different types?

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):

Why don’t we convert template parameters to type in JavaScript?

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.

Where does the return type come from in a function declaration?

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:


1 Answers

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

like image 133
François Andrieux Avatar answered Oct 25 '22 16:10

François Andrieux