我的可变参数模板构造函数隐藏了复制构造函数,防止 class 被复制
My variadic templated constructor hides copy constructor, preventing the class to be copied
我做了一个Vector<numType, numberOfCoords>
class。我对此很满意,这有点奇怪,但它似乎在一开始就起作用了。但是我刚刚发现复制向量是不可能的。
原因是为了让坐标数成为模板,有一个模板化的可变参数构造函数,它需要正确的坐标数。
这是删除实用数学方法后的样子:
template <typename NumType, unsigned char Size>
class Vector
{
public:
using CoordType = NumType;
//Vector(const Vector& v) : values(v.values) {}
//Vector(Vector&& v) : values(std::move(v.values)) {}
template<typename... NumTypes>
constexpr Vector(NumTypes&&... vals) : values{ std::forward<NumTypes>(vals)... }
{
static_assert(sizeof...(NumTypes) == Size, "You must provide N arguments.");
}
Vector(const std::array<NumType, Size>& values) : values(values) {}
Vector(std::array<NumType, Size>&& values) : values(std::move(values)) {}
const NumType& operator[](size_t offset) const { return values[offset]; }
NumType& operator[](size_t offset) { return values[offset]; }
//Vector& operator=(const Vector& other) { values = other.values; }
//Vector& operator=(Vector&& other) { values = std::move(other.values); }
std::array<NumType, Size> values;
};
如您所见 - 现在已注释掉 - 我确实尝试过手动实现复制、移动和赋值操作。它没有效果,错误总是沿着:
cannot convert ‘Vector<int, 3>’ to ‘int’ in initialization
这是因为它仍在尝试使用可变参数构造函数,而不是复制构造函数。
这是一个完整的 工作 损坏的样本:https://ideone.com/Jz86vP
你可能:
SFINAE 你的可变参数构造函数,例如:
template <typename... NumTypes,
std::enable_if_t<sizeof...(NumTypes) == Size
&& std::conjunction<std::is_same<NumType, NumTypes>::value,
int> = 0>
constexpr Vector(NumTypes&&... vals) : values{ std::forward<NumTypes>(vals)... }
{
}
注意:std::conjunction
是C++17,但可以在C++14中完成。
或添加一个标签:
template <typename... NumTypes>
constexpr Vector(struct SomeTag, NumTypes&&... vals) :
values{ std::forward<NumTypes>(vals)... }
{
}
或重新设计class,例如:
template <typename T, std::size_t>
using always_type = T;
template <typename NumType, typename Seq> class VectorImpl;
template <typename NumType, std::size_t ... Is>
class VectorImpl<NumType, std::index_sequence<Is...>>
{
public:
using CoordType = NumType;
VectorImpl(const VectorImpl&) = default;
VectorImpl(VectorImpl&&) = default;
VectorImpl& operator=(const VectorImpl&) = default;
VectorImpl& operator=(VectorImpl&&) = default;
constexpr VectorImpl(always_type<NumType, Is>... vals) : values{ std::forward<NumType>(vals)... }
{
}
VectorImpl(const std::array<NumType, sizeof...(Is)>& values) : values(values) {}
VectorImpl(std::array<NumType, sizeof...(Is)>&& values) : values(std::move(values)) {}
const NumType& operator[](size_t offset) const { return values[offset]; }
NumType& operator[](size_t offset) { return values[offset]; }
std::array<NumType, sizeof...(Is)> values;
};
template <typename T, std::size_t N>
using Vector = VectorImpl<T, std::make_index_sequence<N>>;
我做了一个Vector<numType, numberOfCoords>
class。我对此很满意,这有点奇怪,但它似乎在一开始就起作用了。但是我刚刚发现复制向量是不可能的。
原因是为了让坐标数成为模板,有一个模板化的可变参数构造函数,它需要正确的坐标数。
这是删除实用数学方法后的样子:
template <typename NumType, unsigned char Size>
class Vector
{
public:
using CoordType = NumType;
//Vector(const Vector& v) : values(v.values) {}
//Vector(Vector&& v) : values(std::move(v.values)) {}
template<typename... NumTypes>
constexpr Vector(NumTypes&&... vals) : values{ std::forward<NumTypes>(vals)... }
{
static_assert(sizeof...(NumTypes) == Size, "You must provide N arguments.");
}
Vector(const std::array<NumType, Size>& values) : values(values) {}
Vector(std::array<NumType, Size>&& values) : values(std::move(values)) {}
const NumType& operator[](size_t offset) const { return values[offset]; }
NumType& operator[](size_t offset) { return values[offset]; }
//Vector& operator=(const Vector& other) { values = other.values; }
//Vector& operator=(Vector&& other) { values = std::move(other.values); }
std::array<NumType, Size> values;
};
如您所见 - 现在已注释掉 - 我确实尝试过手动实现复制、移动和赋值操作。它没有效果,错误总是沿着:
cannot convert ‘Vector<int, 3>’ to ‘int’ in initialization
这是因为它仍在尝试使用可变参数构造函数,而不是复制构造函数。
这是一个完整的 工作 损坏的样本:https://ideone.com/Jz86vP
你可能:
SFINAE 你的可变参数构造函数,例如:
template <typename... NumTypes, std::enable_if_t<sizeof...(NumTypes) == Size && std::conjunction<std::is_same<NumType, NumTypes>::value, int> = 0> constexpr Vector(NumTypes&&... vals) : values{ std::forward<NumTypes>(vals)... } { }
注意:
std::conjunction
是C++17,但可以在C++14中完成。或添加一个标签:
template <typename... NumTypes> constexpr Vector(struct SomeTag, NumTypes&&... vals) : values{ std::forward<NumTypes>(vals)... } { }
或重新设计class,例如:
template <typename T, std::size_t> using always_type = T; template <typename NumType, typename Seq> class VectorImpl; template <typename NumType, std::size_t ... Is> class VectorImpl<NumType, std::index_sequence<Is...>> { public: using CoordType = NumType; VectorImpl(const VectorImpl&) = default; VectorImpl(VectorImpl&&) = default; VectorImpl& operator=(const VectorImpl&) = default; VectorImpl& operator=(VectorImpl&&) = default; constexpr VectorImpl(always_type<NumType, Is>... vals) : values{ std::forward<NumType>(vals)... } { } VectorImpl(const std::array<NumType, sizeof...(Is)>& values) : values(values) {} VectorImpl(std::array<NumType, sizeof...(Is)>&& values) : values(std::move(values)) {} const NumType& operator[](size_t offset) const { return values[offset]; } NumType& operator[](size_t offset) { return values[offset]; } std::array<NumType, sizeof...(Is)> values; }; template <typename T, std::size_t N> using Vector = VectorImpl<T, std::make_index_sequence<N>>;