Reputation: 1203
Let's say I have a class which looks like this which should either be constructed by value if T
is a simple type like double
or by reference if T
is more complex.
The code I have so far looks like this:
template<class T>
class Val {
public:
Val() = default;
Val(double v) : _v(v) {}
template<typename U = T>
Val(const &T v,
typename std::enable_if<!std::is_same<U,double>::value, bool>::type = 0)
: _v(v) {}
private:
T _v;
};
Which works, but feels really sketchy, since an additional parameter is introduced into the constructor. Is there a better solution to this problem? It seems like this would be better suited for an overload or template specialization solution? Can this be solved generally for all simple types (int
, float
, double
...)?
Upvotes: 3
Views: 190
Reputation: 218098
You may use boost::call_traits<T>::param_type
template<class T>
class Val {
public:
Val() = default;
Val(boost::call_traits<T>::param_type v) : _v(v) {}
private:
T _v;
};
Upvotes: 1
Reputation: 303537
You only need to have one constructor. It, after all, does the same thing in both cases right? First, define a type trait which, based on T
, is either a value or reference:
template <typename T>
using param_type = std::conditional_t<
is_complex_type<T>::value,
T const&,
T>;
Where is_complex_type
is some appropriate type trait to be determined later. Maybe it's is_fundamental
as other answers proposed.
And then just use it:
template<class T>
class Val {
public:
Val() = default;
Val(param_type<T> v) : _v(v) { }
};
Upvotes: 6
Reputation: 19617
Just a little modified version of your code along with CyberGuy's recommendation of std::is_fundamental
will do what you want.
#include <iostream>
using namespace std;
template <class T>
class Val
{
public:
template <typename U = T>
Val(T v,
typename std::enable_if<std::is_fundamental<U>::value>::type* = 0)
: _v(v)
{
cout << "fundamental" << endl;
}
template <typename U = T>
Val(T const& v,
typename std::enable_if<!std::is_fundamental<U>::value>::type* = 0)
: _v(v)
{
cout << "complex" << endl;
}
private:
T _v;
};
struct A {};
int main()
{
Val<double> v1(1);
Val<char> v2('a');
Val<A> v3(A{});
}
Output:
fundamental
fundamental
complex
Upvotes: 2
Reputation: 2813
There is std::is_fundamental
which should fit you. Best looking solution for me is:
template<class T>
typename std::enable_if< std::is_fundamental<T>::value >::type func(T p_arg){}
template<class T>
typename std::enable_if< !std::is_fundamental<T>::value >::type func(T const &p_arg){}
Upvotes: 4