Reputation: 1902
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
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
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