user2717954
user2717954

Reputation: 1902

Unknown return type of template functions, code repetition when using decltype

In my job, there are several template mathematical classes (e.g matrix).

An object can be implemented using either floats or doubles (or other numerical types but for this matter, it doesn't really matter).

A double object can only interact with another double object. For this matter the function convert() was implemented for various types, with an implementation similar to this:

Matrix<T2> convert(const Matrix<T1>& m, T2 dummy) {
   // create a matrix with type T2 and cast m values into it 
   //  retMatrix(i, j) = (T2)m(i,j)
} 

You would call it with:

auto floatMatrix = convert(doubleMatrix, 0.f);

Or the slightly more verbose:

auto floatMatrix = convert(doubleMatrix, float());

I want to add a function like the one below that will enable a cleaner (IMHO) way to call these functions

template <typename T, typename S>
auto convert(S&& s) -> decltype(convert(s, T())) {
  return convert(s, T());
} 

Now they can be called using:

auto floatMatrix = convert<float>(doubleMatrix);

My question is that my function signature is pretty awkward, I need to repeat the convert(s, T()) both in the decltype and in the actual function body

How do I overcome this?

thanks

edit:

currently, we are not using c++14

edit #2:

the Matrix class was just an example, there are quite a few relevant classes that have the convert() function implemented for them. Each of them already "specialized" like someone suggested in an answer below (deleted meanwhile). I would like to adjust the way convert() is called without re implementing everything

edit #3:

supported types are obviously other than only float and double. please treat the example I gave as an example and not the actual problem I'm trying to solve

the "dummy" functions are already implemented, I was trying to make it work with minimal effort, instead of refactoring 30 functions and all usages

I don't think the question is so far fetched considering cpp14 allows to just remove the -> decltype() thingy...

Upvotes: 4

Views: 388

Answers (2)

Gem Taylor
Gem Taylor

Reputation: 5613

One option might be helper classes that know the conversion type from Matrix for T to Matrix, but they are no prettier than the decltype statement, which is readable and local to the code.

Could Matrix derive from a base class that knows how to generate Matrix from T? Perhaps as a member so you can write:

class MatrixBase
{
  public:
    template <class T> class To 
   { typedef Matrix<T> To; };
};

class Matrix<int>:public MatrixBase {
  // ...
};

All this just to write: -> S::To<T>::To

As you say, come the C++14 revolution you can do the fully automatic return type thing.

Upvotes: 0

Vitali
Vitali

Reputation: 3695

A little confusing why the need for templates in the first place instead of function overloading:

Matrix<double> convert(const Matrix<float>& m) {
    // ...
}

Matrix<float> convert(const Matrix<double>& m) {
    // ...
}

float->float and double->double don't seem like meaningful operations that need to be preserved so actually making that a compiler error seems beneficial (whereas the template mechanism might actually succeed and just create an unnecessary copy).

Also the need for the dummy parameter in the first place is confusing without a more complete example.

If you're set on templates (e.g. types go beyond just these two):

template <typename T2, typename T1>
Matrix<T2> convert(const Matrix<T1>& m) {
}

If you're trying to write 1 single generic conversion function across all your other conversion functions you have no way of simplifying what you wrote until C++14 (I mean there are other ways to write it but it seems unlikely to be simpler).

Upvotes: 1

Related Questions