我试图编写一个包装类,它有条件地禁用四个特殊的成员函数(复制构造、移动构造、复制分配和移动分配),下面是我用于测试目的的快速草稿:
enum class special_member : uint8_t {
copy_ctor, move_ctor,
copy_asgn, move_asgn
};
template<typename MemberType, special_member...>
struct _disabled_wrapper {
public:
constexpr _disabled_wrapper(MemberType type) : _type(type) {}
public:
constexpr MemberType& unwrapped() { return _type; }
constexpr const MemberType& unwrapped() const { return _type; }
private:
MemberType _type;
};
template<typename MemberType, special_member ... Disables>
struct _disabled_wrapper<MemberType, special_member::copy_ctor, Disables...>
{
private:
using _parent_t = _disabled_wrapper<MemberType, Disables...>;
public:
constexpr _disabled_wrapper(const _parent_t& parent) : _parent(parent) {}
constexpr _disabled_wrapper(const _disabled_wrapper&) = delete;
constexpr _disabled_wrapper(_disabled_wrapper&&) = default;
constexpr _disabled_wrapper& operator=(const _disabled_wrapper&) = default;
constexpr _disabled_wrapper& operator=(_disabled_wrapper&&) = default;
public:
constexpr MemberType& unwrapped() { return _parent.unwrapped(); }
constexpr const MemberType& unwrapped() const { return _parent.unwrapped(); }
private:
_parent_t _parent;
};
template<typename MemberType, special_member ... Disables>
struct _disabled_wrapper<MemberType, special_member::move_ctor, Disables...>
{
public: //Todo: Make private post fix.
using _parent_t = _disabled_wrapper<MemberType, Disables...>;
public:
constexpr _disabled_wrapper(const _parent_t& parent) : _parent(parent) {}
constexpr _disabled_wrapper(const _disabled_wrapper&) = default;
constexpr _disabled_wrapper(_disabled_wrapper&&) = delete;
constexpr _disabled_wrapper& operator=(const _disabled_wrapper&) = default;
constexpr _disabled_wrapper& operator=(_disabled_wrapper&&) = default;
public:
constexpr MemberType& unwrapped() { return _parent.unwrapped(); }
constexpr const MemberType& unwrapped() const { return _parent.unwrapped(); }
private:
_parent_t _parent;
};
template<typename MemberType, special_member ... Disables>
struct _disabled_wrapper<MemberType, special_member::copy_asgn, Disables...>
{
private:
using _parent_t = _disabled_wrapper<MemberType, Disables...>;
public:
constexpr _disabled_wrapper(const _parent_t& parent) : _parent(parent) {}
constexpr _disabled_wrapper(const _disabled_wrapper&) = default;
constexpr _disabled_wrapper(_disabled_wrapper&&) = default;
constexpr _disabled_wrapper& operator=(const _disabled_wrapper&) = delete;
constexpr _disabled_wrapper& operator=(_disabled_wrapper&&) = default;
public:
constexpr MemberType& unwrapped() { return _parent.unwrapped(); }
constexpr const MemberType& unwrapped() const { return _parent.unwrapped(); }
private:
_parent_t _parent;
};
template<typename MemberType, special_member ... Disables>
struct _disabled_wrapper<MemberType, special_member::move_asgn, Disables...>
{
private:
using _parent_t = _disabled_wrapper<MemberType, Disables...>;
public:
constexpr _disabled_wrapper(const _parent_t& parent) : _parent(parent) {}
constexpr _disabled_wrapper(const _disabled_wrapper&) = default;
constexpr _disabled_wrapper(_disabled_wrapper&&) = default;
constexpr _disabled_wrapper& operator=(const _disabled_wrapper&) = default;
constexpr _disabled_wrapper& operator=(_disabled_wrapper&&) = delete;
public:
constexpr MemberType& unwrapped() { return _parent.unwrapped(); }
constexpr const MemberType& unwrapped() const { return _parent.unwrapped(); }
private:
_parent_t _parent;
};除三种情况(<move_ctor, move_asgn>、<copy_ctor, move_asgn>和<copy_ctor, move_ctor, move_asgn>)外,上述代码功能正确。具体来说,下面代码中的断言失败了,这使我相信,在move_ctor部分专门化的_disabled_wrapper中,由于某些原因,默认的移动赋值运算符没有被删除,尽管它的非静态成员_parent的移动分配被删除了。cppreference.com声明:
如果下列任何一项都是正确的,则将类T的隐式声明或默认移动赋值操作符定义为已删除:
重载解析忽略已删除的隐式声明的移动赋值运算符。
这使我相信,根据标准,移动赋值操作符确实应该删除(第三点)。我遗漏了什么,或者,如果可能的话,如何使包装类按照预期的方式工作,而无需手动输入所有可能的专门化?谢谢。
int main() {
using type = _disabled_wrapper<int, special_member::move_ctor, special_member::move_asgn>;
//Passes, hence member variable has its move_assignment deleted as intended.
static_assert(std::is_move_assignable_v<type::_parent_t> == false);
//Fails here! Move assignment defined?
static_assert(std::is_move_assignable_v<type> == false);
return 0;
}发布于 2022-06-16 16:51:34
引用中的最后一条语句“已删除、隐式声明的移动赋值运算符被重载解析忽略”。更准确地说:
被定义为已删除的默认移动赋值运算符将被重载解析忽略。
type有一个默认的移动赋值操作符,它被定义为已删除,因为它在基类中被删除。
因此,重载解析忽略了这个操作符。
因此,来自rvalue的赋值选择复制分配。
因此,type是可移动的,因为它是可复制的。
https://stackoverflow.com/questions/72645574
复制相似问题