c++ 模板 class 根据类型通过 ref 传递构造函数
c++ template class pass constructor by ref depending on type
假设我有一个看起来像这样的 class 如果 T
是像 double
这样的简单类型,它应该按值构造,如果 T
则应该按引用构造]比较复杂。
我目前的代码如下所示:
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;
};
这行得通,但感觉真的很粗略,因为在构造函数中引入了一个额外的参数。这个问题有更好的解决方案吗?这似乎更适合重载或模板专业化解决方案?对于所有简单类型(int
、float
、double
...),这是否可以普遍解决?
有 std::is_fundamental
应该适合您。对我来说最好看的解决方案是:
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){}
只需对您的代码稍作修改,再加上 CyberGuy 对 std::is_fundamental
的建议,即可满足您的需求。
#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{});
}
输出:
fundamental
fundamental
complex
你只需要一个构造函数。毕竟,它在两种情况下都做同样的事情,对吧?首先,定义一个类型特征,它基于 T
,是一个值或引用:
template <typename T>
using param_type = std::conditional_t<
is_complex_type<T>::value,
T const&,
T>;
其中 is_complex_type
是稍后确定的一些适当的类型特征。也许是 is_fundamental
正如其他答案所建议的那样。
然后直接使用它:
template<class T>
class Val {
public:
Val() = default;
Val(param_type<T> v) : _v(v) { }
};
您可以使用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;
};
假设我有一个看起来像这样的 class 如果 T
是像 double
这样的简单类型,它应该按值构造,如果 T
则应该按引用构造]比较复杂。
我目前的代码如下所示:
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;
};
这行得通,但感觉真的很粗略,因为在构造函数中引入了一个额外的参数。这个问题有更好的解决方案吗?这似乎更适合重载或模板专业化解决方案?对于所有简单类型(int
、float
、double
...),这是否可以普遍解决?
有 std::is_fundamental
应该适合您。对我来说最好看的解决方案是:
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){}
只需对您的代码稍作修改,再加上 CyberGuy 对 std::is_fundamental
的建议,即可满足您的需求。
#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{});
}
输出:
fundamental
fundamental
complex
你只需要一个构造函数。毕竟,它在两种情况下都做同样的事情,对吧?首先,定义一个类型特征,它基于 T
,是一个值或引用:
template <typename T>
using param_type = std::conditional_t<
is_complex_type<T>::value,
T const&,
T>;
其中 is_complex_type
是稍后确定的一些适当的类型特征。也许是 is_fundamental
正如其他答案所建议的那样。
然后直接使用它:
template<class T>
class Val {
public:
Val() = default;
Val(param_type<T> v) : _v(v) { }
};
您可以使用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;
};