Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deduce return type of operator/function for templates

Tags:

c++

templates

Is something like this possible?

// We can even assume T and U are native C++ types
template<typename T, typename U>
magically_deduce_return_type_of(T * U) my_mul() { return T * U; }

Or would somebody have to hack up a return_type struct and specialize it for every pair of native types?

like image 469
Chris Avatar asked Sep 30 '10 13:09

Chris


People also ask

What is template deduction?

Template argument deduction is used when selecting user-defined conversion function template arguments. A is the type that is required as the result of the conversion. P is the return type of the conversion function template.

What is C++ type deduction?

Type inference or deduction refers to the automatic detection of the data type of an expression in a programming language. It is a feature present in some strongly statically typed languages. In C++, the auto keyword(added in C++ 11) is used for automatic type deduction.

What does Decltype auto do?

decltype(auto) is primarily useful for deducing the return type of forwarding functions and similar wrappers, where you want the type to exactly “track” some expression you're invoking.

What is Typename C++?

" typename " is a keyword in the C++ programming language used when writing templates. It is used for specifying that a dependent name in a template definition or declaration is a type.


4 Answers

Heard of decltype?

In C++0x you can do

template<class T, class U>
auto mul(T x, U y) -> decltype(x*y)
{
    return x*y;
}
like image 177
Prasoon Saurav Avatar answered Oct 29 '22 00:10

Prasoon Saurav


You can do this in non C++0x code:

template<typename T, typename U> class Mul
{
  T t_;
  U u_;
public:
  Mul(const T& t, const U& u): t_(t), u_(u) {}
  template <class R>
  operator R ()
  {
    return t_ * u_;
  }
};

template<typename T, typename U>
Mul<T, U> mul(const T& t, const U& u)
{
  return Mul<T, U>(t, u);
}

Usage: char t = 3; short u = 4; int r = mul(t, u);

Here we have two type deductions. We implicitly declare return type by usage, not exactly decltype(T*U)

like image 32
naixx Avatar answered Oct 29 '22 00:10

naixx


I'm using Visual Studio 2008, so I had to come up with a non C++0x way. I ended up doing something like this.

template<typename T> struct type_precedence { static const int value = -1; };
template< > struct type_precedence<long double> { static const int value = 0; };
template< > struct type_precedence<double> { static const int value = 1; };
template< > struct type_precedence<float> { static const int value = 2; };
template< > struct type_precedence<unsigned long long> { static const int value = 3; };
template< > struct type_precedence<long long> { static const int value = 4; };
template< > struct type_precedence<unsigned long> { static const int value = 5; };
template< > struct type_precedence<long> { static const int value = 6; };
template< > struct type_precedence<unsigned int> { static const int value = 7; };
template< > struct type_precedence<int> { static const int value = 8; };
template< > struct type_precedence<unsigned short> { static const int value = 9; };
template< > struct type_precedence<short> { static const int value = 10; };
template< > struct type_precedence<unsigned char> { static const int value = 11; };
template< > struct type_precedence<char> { static const int value = 12; };
template< > struct type_precedence<bool> { static const int value = 13; };

/////////////////////////////////////////////////////////////////////////////////////////

template<typename T, typename U, bool t_precedent = ((type_precedence<T>::value) <= (type_precedence<U>::value))>
struct precedent_type { 
    typedef T t; 
};
template<typename T, typename U>
struct precedent_type<T,U,false> { 
    typedef U t;
};

/////////////////////////////////////////////////////////////////////////////////////////

template<typename T, typename U>
typename precedent_type<T,U>::t my_mul() { return T * U; }

EDIT: Here's the example - I'm actually doing this to multiply vectors. It looks something like this:

template<int N, typename T, typename U>
vec<N,typename precedent_type<T,U>::t> operator *(const vec<N,T>& v1,const vec<N,U>& v2) {
    ...
}

...

double3 = float3 * double3;
float4 = float4 * int4;
etc.
like image 25
Chris Avatar answered Oct 28 '22 22:10

Chris


http://www2.research.att.com/~bs/C++0xFAQ.html#decltype

like image 28
David Avatar answered Oct 28 '22 22:10

David