简体   繁体   English

c ++模板类根据类型通过ref传递构造函数

[英]c++ template class pass constructor by ref depending on type

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. 假设我有一个看起来像这样的类,如果T是一个像double这样的简单类型,或者如果T更复杂,那么它应该由值构造。

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 ...)? 对于所有简单类型( intfloatdouble ......),这通常可以解决吗?

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: 首先,定义一个基于T的类型特征,它是值或引用:

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. 其中is_complex_type是稍后要确定的某种适当的类型特征。 Maybe it's is_fundamental as other answers proposed. 也许这是is_fundamental其他答案建议。

And then just use it: 然后使用它:

template<class T>
class Val {
public:
    Val() = default;
    Val(param_type<T> v) : _v(v) { }
};

There is std::is_fundamental which should fit you. std::is_fundamental应该适合你。 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){}

Just a little modified version of your code along with CyberGuy's recommendation of std::is_fundamental will do what you want. 只需对代码进行一些修改后的版本以及Cyber​​Guy对std::is_fundamental的推荐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{});
}

Output: 输出:

fundamental
fundamental
complex

You may use boost::call_traits<T>::param_type 您可以使用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;
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM