In C++17, is there a way to prevent template argument deduction from a call to a call class constructor?
In the following code, I define a template class with an argument T that is meant to be the "precision" (float, double, long double) of the data stored. I want it to be double by default and I don't want the value given to the constructor to define the type of T even when it is not explicitly specified. I also want objects with the same precision to be of the same type (so having a second template parameter is not an option)
By the way, this is how it worked the situation before C++17. Does it mean that backward compatibility has been lost?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
#include <iostream>
template <typename T = double>
class heading{
public:
T value;
public:
heading(T h):value(h+0.333){}
};
int main(){
heading a(2); //this creates a heading<int> but I want a heading<double>
//unless explicitly specified
std::cout << a.value << std::endl;
}
Ok, I found this solution. It works because template argument deduction doesn't process decltype() expressions.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
#include <iostream>
template <typename T = double>
class heading{
public:
typedefdecltype(T()) S;
T value;
public:
heading(S h):value(h+0.333){}
};
int main(){
heading a(2); //now this does not define T as an int!
//and the default type double is used
std::cout << a.value << std::endl;
}
2. Change the type of the converting constructor's parameter: heading(std::common_type_t<T> h):value(h+0.333){}
This is a old library author's trick to disable function template argument deduction. std::common_type_t<T> is equivalent for these purposes to the identity meta-function. Same idea as the decltype hack.
Maybe suggestion 1. isn't the best idea. I am not very familiar with this feature.