我有一个RAII包装器,包装了一个指向库中Foo
的指针Foo*
。
该类大致如下:
struct Handle{
Foo* p;
Handle(): p(foo_new()){}
Handle(Handle&& f): p(std::exchange(f.p, nullptr)){}
Handle(const Handle& f){
p = foo_clone(f.p);
}
};
为了简洁起见,错误处理和赋值运算符已被省略。
现在的问题是,
foo_clone
在一个库版本中可用,但在早期版本中不可用,而封装应该支持两种情况。我没有*_VERSION
宏可以检查,因此需要在C++中完成,而不是在预处理器中。我想到了以下方法:
template<class T, decltype(foo_clone(std::declval<T>().p)) = nullptr>
Handle(const T& f){...}
但这样是不行的:定义的移动构造函数要求我原封不动地添加一个复制构造函数,即Handle(const Handle&)
,否则编译器会认为复制构造函数被隐式删除,无法使用任何模板技巧。
我该怎么办?
foo_clone
,它会返回一个指针,因此该方法类似于template<T, std::enable_if_t<...>* = nullptr>
。当然,如果要使用布尔解决方案,则必须使用另一种方法。 - Flamefirestd::declval<T>::p
应该是std::declval<T>().p
。这可能被认为是笔误,或者与您的问题相关。 - Jarod42