Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overriding return type in function template specialization

Tags:

c++

templates

I would like to specialize a function template such that the return type changes depending on the type of the template argument.

class ReturnTypeSpecialization
{
public:
    template<typename T>
    T Item();
};

// Normally just return the template type
template<typename T>
T ReturnTypeSpecialization::Item() { ... }

// When a float is specified, return an int
// This doesn't work:
template<float>
int ReturnTypeSpecialization::Item() { ... }

Is this possible? I can't use C++11.

like image 670
sourcenouveau Avatar asked Apr 09 '13 20:04

sourcenouveau


People also ask

Can a template function override?

You cannot define a virtual template method. override only works for virtual methods, and you can only override methods with the same signature.

What is function template specialization?

The act of creating a new definition of a function, class, or member of a class from a template declaration and one or more template arguments is called template instantiation. The definition created from a template instantiation is called a specialization. A primary template is the template that is being specialized.

What is the difference between generic class template and specialization template?

Key differences between generics and C++ templates: Generics are generic until the types are substituted for them at runtime. Templates are specialized at compile time so they are not still parameterized types at runtime. The common language runtime specifically supports generics in MSIL.

How do you call a template function in C++?

A function template starts with the keyword template followed by template parameter(s) inside <> which is followed by the function definition. In the above code, T is a template argument that accepts different data types ( int , float , etc.), and typename is a keyword.


2 Answers

Since the specialization has to agree with the base template on the return type, you can make it so by adding a "return type trait", a struct you can specialize and draw the true return type from:

// in the normal case, just the identity
template<class T>
struct item_return{ typedef T type; };

template<class T>
typename item_return<T>::type item();

template<>
struct item_return<float>{ typedef int type; };
template<>
int item<float>();

Live example.

Note that you might want to stick to the following, so you only need to update the return-type in the item_return specialization.

template<>
item_return<float>::type foo<float>(){ ... }
// note: No `typename` needed, because `float` is not a dependent type
like image 57
Xeo Avatar answered Oct 11 '22 00:10

Xeo


Do all of the specialization in a worker class and use a simple function as a wrapper that will be specialized implicitly.

#include <iostream>
using std::cout;

// worker class -- return a reference to the given value
template< typename V > struct worker
   {
   typedef V const & type;
   static type get( V const & v ) { return v; }
   };

// worker class specialization -- convert 'unsigned char' to 'int'
template<> struct worker<unsigned char>
   {
   typedef int type;
   static type get( unsigned char const & v ) { return v; }
   };

// mapper function
template< typename V > typename worker<V>::type mapper( V const & v )
   {
   return worker<V>::get(v);
   }

int main()
   {
   char a='A';
   unsigned char b='B';
   cout << "a=" << mapper(a) << ", b=" << mapper(b) << "\n";
   }

In this example, the specialization of unsigned char causes it to be converted to an int so that cout will display it as a number instead of as a character, generating the following output...

a=A, b=66
like image 7
Brent Bradburn Avatar answered Oct 11 '22 00:10

Brent Bradburn