例如,我可以使用 CRTP 做这样的事情:
template<typename Self>
struct Sharable {
int count = 0;
template<typename... Args>
static Self *create(Args &&...args) {
Self *res = new Self(std::forward<Args>(args)...);
res->count = 1;
return res;
}
Self *dup() {
++count;
return static_cast<Self *>(this);
}
void drop() {
if (--count == 0) {
delete static_cast<Self *>(this);
}
}
};
struct Object : Sharable<Object> {
int val1;
Object(int v1) : val1(v1) {}
};
int main() {
Object *ptr = Object::create(1);
}
但是,问题在于,使用这种模式,如果有一个类继续继承自
Object
类,那么一方面,子类中会出现两个重复的 count
成员,而另一方面另一方面,会存在create
、dup
、drop
等方法的多个副本,导致方法调用不明确。
struct Child : Object, Sharable<Child> {
int val2;
Child(int v1, int v2) : Object(v1), val2(v2) {}
};
int main() {
Child *ptr = Child::create(1, 2);
// error: member 'create' found in multiple base classes of different types
}
我了解到 C++23 中的推导此功能可以做一些相关的事情:
struct SharedMemory {
std::size_t count = 0;
template<typename Self>
Self *dup() {
++count;
return static_cast<Self *>(this);
}
template<typename Self>
void drop() {
if (--count == 0) {
delete static_cast<Self *>(this);
}
}
};
但是,这似乎只适用于那些非静态方法(
dup
和drop
),是否可以对静态方法执行相同的操作? (如果没有C++23特性就可以做到这一点就更好了)
注意:这里,我希望
create
成为Shared
类的成员方法,而不是在类外将其实现为模板函数,因为我需要以其他方式管理其他一些类的内存(例如,可能有一些其他类继承自另一个基类Global
而不是Sharable
,其create
,dup
,drop
方法在全局内存上操作)
通过虚拟继承并为 CRTP 提供基础,您可能会这样做:
struct RefCounter
{
virtual ~RefCounter() = default;
int count = 1;
};
template<typename Self, typename... Bases>
struct Sharable : protected virtual RefCounter, public Bases...
{
Sharable(Bases... bases) : Bases(bases)... {}
template<typename... Args>
static Self *create(Args &&...args) {
return new Self(std::forward<Args>(args)...);
}
Self *dup() {
++count;
return static_cast<Self *>(this);
}
void drop() {
if (--count == 0) {
delete static_cast<Self *>(this);
}
}
};
struct Object : Sharable<Object> {
int val1;
Object(int v1) : val1(v1) {}
};
struct Child : Sharable<Child, Object> {
int val2;
Child(int v1, int v2) : Sharable(v1), val2(v2) {}
};