如何在保留默认移动构造函数和赋值的同时构造公共数据?
How can I structure common data while retaining defaulted move ctor and assignment?
我有几个 classes 有共同点:它们的构造方式和它们保存的数据。然而,每个人都有一个独特的dtor。因此,尝试删除代码重复并使它们从基础 class 继承似乎是显而易见的。所以我从这个开始:
class base{
protected:
int data;
public:
base() = default;
base(const base &) = delete;
base& operator=(const base &) = delete;
base(base &&) = default;
base& operator=(base &&) = default;
};
class derived: public base{
public:
~derived() {}
};
但是,问题出现了。我做不到
derived d;
derived e(std::move(d));
原因是因为 derived
声明了一个 dtor,这意味着移动 ctor/assignment 不会生成。所以我的下一个想法是反转继承,我想到了这个。因为我(在我原来的例子中)有多个派生和一个单一的基地,我想这样做的方式是有多个基地和一个单一的派生,这将被模板化以指向不同的基地。
class base1{
public:
~base1() {}
};
class base2{
public:
~base2() {}
};
template<class T>
class derived: public T{
protected:
int data;
public:
derived() = default;
derived(const derived &) = delete;
derived& operator=(const derived &) = delete;
derived(derived &&) = default;
derived& operator=(derived &&) = default;
};
using derived1 = derived<base1>;
using derived2 = derived<base2>;
一切都很好,可以编译!
但是,base1
和 base2
需要访问 base
中的元素 data
,所以我想将这些基数做成模板化的 class,这样它们的函数就可以访问 data
。此外,这些基础实际上有时是模板化的,因此我也需要添加此功能。我到目前为止是这样的:
template<class T1, class T2>
class base1{
public:
~base1() {
std::cout<<T1::data;
}
};
template<class T>
class base2{
public:
~base2() {
std::cout<<T::data;
}
};
template<template <class, class...> class T, class... Ts>
class derived: public T<typename derived, Ts...>{
protected:
int data;
public:
derived() = default;
derived(const derived &) = delete;
derived& operator=(const derived &) = delete;
derived(derived &&) = default;
derived& operator=(derived &&) = default;
};
using derived1int = derived<base1<int>>;
using derived1float = derived<base1<float>>;
using derived2 = derived<base2>;
但是,我敢肯定其中有很多错误。我现在在 GCC 4.9 中得到的编译器错误是(当仅使用 derived2
时)是模板参数 1 在 class 派生中无效。
尽管评论中提出了有效论点,但我还是设法创建了模板。这是为了防止其他人需要计算模板部分:
template<class T1, class Data>
class base1{
public:
~base1() {
std::cout<<static_cast<T1*>(this)->data << " " <<typeid(std::declval<Data>()).name();
}
};
template<class T>
class base2{
public:
~base2() {
std::cout<< static_cast<T*>(this)->data;
}
};
template<template <class, class...> class T, class ... Ts >
class derived: public T< derived<T, Ts...>, Ts...>{
friend class T<derived<T, Ts...>, Ts...>;
int data = 0;
public:
derived() = default;
derived(const derived &) = delete;
derived& operator=(const derived &) = delete;
derived(derived && d){
std::swap(data, d.data);
}
derived& operator=(derived && d){
std::swap(data, d.data);
return *this;
}
};
using derived1int = derived<base1, int>;
using derived1float = derived<base1, float>;
using derived2 = derived<base2>;
我有几个 classes 有共同点:它们的构造方式和它们保存的数据。然而,每个人都有一个独特的dtor。因此,尝试删除代码重复并使它们从基础 class 继承似乎是显而易见的。所以我从这个开始:
class base{
protected:
int data;
public:
base() = default;
base(const base &) = delete;
base& operator=(const base &) = delete;
base(base &&) = default;
base& operator=(base &&) = default;
};
class derived: public base{
public:
~derived() {}
};
但是,问题出现了。我做不到
derived d;
derived e(std::move(d));
原因是因为 derived
声明了一个 dtor,这意味着移动 ctor/assignment 不会生成。所以我的下一个想法是反转继承,我想到了这个。因为我(在我原来的例子中)有多个派生和一个单一的基地,我想这样做的方式是有多个基地和一个单一的派生,这将被模板化以指向不同的基地。
class base1{
public:
~base1() {}
};
class base2{
public:
~base2() {}
};
template<class T>
class derived: public T{
protected:
int data;
public:
derived() = default;
derived(const derived &) = delete;
derived& operator=(const derived &) = delete;
derived(derived &&) = default;
derived& operator=(derived &&) = default;
};
using derived1 = derived<base1>;
using derived2 = derived<base2>;
一切都很好,可以编译!
但是,base1
和 base2
需要访问 base
中的元素 data
,所以我想将这些基数做成模板化的 class,这样它们的函数就可以访问 data
。此外,这些基础实际上有时是模板化的,因此我也需要添加此功能。我到目前为止是这样的:
template<class T1, class T2>
class base1{
public:
~base1() {
std::cout<<T1::data;
}
};
template<class T>
class base2{
public:
~base2() {
std::cout<<T::data;
}
};
template<template <class, class...> class T, class... Ts>
class derived: public T<typename derived, Ts...>{
protected:
int data;
public:
derived() = default;
derived(const derived &) = delete;
derived& operator=(const derived &) = delete;
derived(derived &&) = default;
derived& operator=(derived &&) = default;
};
using derived1int = derived<base1<int>>;
using derived1float = derived<base1<float>>;
using derived2 = derived<base2>;
但是,我敢肯定其中有很多错误。我现在在 GCC 4.9 中得到的编译器错误是(当仅使用 derived2
时)是模板参数 1 在 class 派生中无效。
尽管评论中提出了有效论点,但我还是设法创建了模板。这是为了防止其他人需要计算模板部分:
template<class T1, class Data>
class base1{
public:
~base1() {
std::cout<<static_cast<T1*>(this)->data << " " <<typeid(std::declval<Data>()).name();
}
};
template<class T>
class base2{
public:
~base2() {
std::cout<< static_cast<T*>(this)->data;
}
};
template<template <class, class...> class T, class ... Ts >
class derived: public T< derived<T, Ts...>, Ts...>{
friend class T<derived<T, Ts...>, Ts...>;
int data = 0;
public:
derived() = default;
derived(const derived &) = delete;
derived& operator=(const derived &) = delete;
derived(derived && d){
std::swap(data, d.data);
}
derived& operator=(derived && d){
std::swap(data, d.data);
return *this;
}
};
using derived1int = derived<base1, int>;
using derived1float = derived<base1, float>;
using derived2 = derived<base2>;