具有复制构造函数的enable_if [英] enable_if with copy constructors
问题描述
我正在第一次尝试
作为一个玩具示例,这是一个简单的静态 vector
类,我想为其定义一个副本构造函数,但其行为取决于矢量的相对大小:
- 只需将数据复制到较小或相同大小的向量中
- 将数据复制到更大的向量中,然后用零填充其余部分
所以 vector
类是:
模板< size_t _Size>类向量{双重_data [_Size];上市:向量(){std :: fill(_data,_data + _Size,0.0);}const double * data()const{返回_data;}//...};
复制构造函数应支持以下内容:将 v3
的前两个元素复制到 v2
:
Vector< 3>v3;向量2.v2(v3);
我尝试了行为1的副本构造函数,如下所示,它可以编译:
模板< size_t _OtherSize,typename = typename std :: enable_if_t< _Size< = _OtherSize>>Vector(const Vector< _OtherSize>& v):Vector(){std :: copy(v.data(),v.data()+ _Size,_data);}
,但是即使 enable_if
条件是互斥的,编译器也无法将其与行为2区分开.
模板< size_t _OtherSize,typename = typename std :: enable_if_t< _OtherSize<_Size>>Vector(const Vector< _OtherSize>& v):Vector(){std :: copy(v.data(),v.data()+ _OtherSize,_data);std :: fill(_data + _OtherSize,_data + _Size,0.0);}
我还尝试将 enable_if
放到参数中,但是它不能推断出 _OtherSize
的值:
模板< size_t _OtherSize>向量(const typename std :: enable_if_t< _Size< = _OtherSize,向量< _OtherSize>>&v):Vector(){std :: copy(v.data(),v.data()+ _Size,_data);}
执行此操作的方式是什么(使用 enable_if
,而不是简单的 if
语句)?
忽略默认值,这些构造函数的 both 的签名为
模板< size_t N,类型名>向量(const Vector< N&)
也就是说,它们最终是相同的.
区分它们的一种方法是使模板参数类型直接取决于 enable_if
的条件:
模板< size_t _OtherSize,std :: enable_if_t<(_ Size< = _OtherSize),int>= 0>Vector(const Vector< _OtherSize>& v):Vector(){std :: copy(v.data(),v.data()+ _Size,_data);}模板< size_t _OtherSize,std :: enable_if_t<(_ OtherSize< _Size),int>= 0>Vector(const Vector< _OtherSize>& v):Vector(){std :: copy(v.data(),v.data()+ _OtherSize,_data);std :: fill(_data + _OtherSize,_data + _Size,0.0);}
顺便说一句,像 _Size
和 _OtherSize
之类的名称保留用于实现,因此对于用户代码而言是非法的–丢失了下划线和/或大写字母.>
此外,正如@StoryTeller所暗示的那样,您也不希望在 _OtherSize == _Size
时应用第一个构造函数,因为编译器生成的副本构造函数具有理想的行为.对于相同大小的 Vector
来说,该构造函数已经不如复制构造函数专门,因此无论如何在重载解析期间都不会选择它,但是最好通过切换< =
到<
.
I am trying std::enable_if
for the first time and struggling. Any guidance would be appreciated.
As a toy example, here is a simple static vector
class, for which I want to define a copy constructor, but the behavior depends on the relative sizes of the vectors:
- just copy data into a smaller or same-sized vector
- copy data into a larger vector and then pad the rest with zeroes
So the vector
class is:
template <size_t _Size>
class Vector
{
double _data[_Size];
public:
Vector()
{
std::fill(_data, _data + _Size, 0.0);
}
const double* data() const
{
return _data;
}
// ...
};
The copy constructor should support something like this: copying the first 2 elements of v3
into v2
:
Vector<3> v3;
Vector<2> v2(v3);
I tried a copy constructor for behavior 1. like this, which compiles:
template <size_t _OtherSize,
typename = typename std::enable_if_t<_Size <= _OtherSize>>
Vector(const Vector<_OtherSize>& v) : Vector()
{
std::copy(v.data(), v.data() + _Size, _data);
}
but the compiler cannot distinguish this from behavior 2. even though the enable_if
conditions are mutually exclusive.
template <size_t _OtherSize,
typename = typename std::enable_if_t<_OtherSize < _Size>>
Vector(const Vector<_OtherSize>& v) : Vector()
{
std::copy(v.data(), v.data() + _OtherSize, _data);
std::fill(_data + _OtherSize, _data + _Size, 0.0);
}
I also tried putting enable_if
in the argument instead, but it couldn't deduce the value of _OtherSize
:
template <size_t _OtherSize>
Vector(const typename std::enable_if_t<_Size <= _OtherSize,
Vector<_OtherSize>> & v)
: Vector()
{
std::copy(v.data(), v.data() + _Size, _data);
}
What is the way to do this (using enable_if
, not a simple if
statement)?
Ignoring defaults, the signature of both of those constructors is
template <size_t N, typename>
Vector(const Vector<N>&)
I.e., they're ultimately the same.
One way to differentiate them is to make the template parameter type directly dependent on enable_if
's condition:
template <size_t _OtherSize,
std::enable_if_t<(_Size <= _OtherSize), int> = 0>
Vector(const Vector<_OtherSize>& v) : Vector()
{
std::copy(v.data(), v.data() + _Size, _data);
}
template <size_t _OtherSize,
std::enable_if_t<(_OtherSize < _Size), int> = 0>
Vector(const Vector<_OtherSize>& v) : Vector()
{
std::copy(v.data(), v.data() + _OtherSize, _data);
std::fill(_data + _OtherSize, _data + _Size, 0.0);
}
As an aside, names like _Size
and _OtherSize
are reserved for the implementation and thus illegal for user code – lose the underscore and/or the capital letter.
Also, as @StoryTeller hinted at, you don't want the first constructor to apply when _OtherSize == _Size
, as the compiler-generated copy constructor has ideal behavior. Said constructor is already less specialized than the copy constructor for same-sized Vector
s, so it won't be selected during overload resolution anyway, but it would be best to make the intent clear by switching <=
to <
.
这篇关于具有复制构造函数的enable_if的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!