C++ 复制和移动语义的折叠重载

C++ 复制和移动语义的折叠重载,c++,c++11,copy,move-semantics,api-design,C++,C++11,Copy,Move Semantics,Api Design,许多方法具有复制和移动语义的重载。例如,从另一种类型构造和赋值 T(const U&); T(U&&); T& operator=(const U&); T& operator=(U&&); 通常情况下,这两种重载的实现非常相似,这会导致代码冗余。所以我在考虑把这两个合并成一个 我发现实际使用的一种方法是通过值传递,并让值构造完成这个任务。比如说, constexpr atomic_shared_ptr(shared_ptr&l

许多方法具有复制和移动语义的重载。例如,从另一种类型构造和赋值

T(const U&);
T(U&&);

T& operator=(const U&);
T& operator=(U&&);
通常情况下,这两种重载的实现非常相似,这会导致代码冗余。所以我在考虑把这两个合并成一个

我发现实际使用的一种方法是通过值传递,并让值构造完成这个任务。比如说,

constexpr atomic_shared_ptr(shared_ptr<T> desired) noexcept;
与构造/赋值情况不同,根据比较结果,
d
可能并不总是被复制。如果
d
是按值传递的,那么它将始终被复制,而且复制成本不低

我提出的另一个解决方案是使用转发引用

template <typename U>
bool compare_exchange_weak(std::shared_ptr<T>&, U&& d...
  ... std::forward<U>(d) ...
模板
布尔比较交换弱(std::共享ptr&,U&&d。。。
…标准::转发(d)。。。
然而,该公式过于允许/容忍


任何其他想法或建议?

您可以约束模板:

template <typename U>
std::enable_if_t<std::is_same_v<std::decay_t<U>,std::shared_ptr<T>>,bool> 
compare_exchange_weak(std::shared_ptr<T>&, U&& d...
  ... std::forward<U>(d) ...
模板
std::如果启用,则启用
比较\U交换\U弱(标准::共享\U ptr&,U&&d。。。
…标准::转发(d)。。。
有了它,它可能更具可读性:

template<class T,class V>
concept Same_d = std::is_same_v<std::decay_t<T>,std::decay_t<U>>;

bool compare_exchange_weak(std::shared_ptr<T>&, Same_d{U}<std::shared_ptr<T>>&& d...
  ... std::forward<U>(d) ...
模板
概念相同=标准::是相同的;
bool比较交换弱(std::shared_ptr&,Same_d{U}&&d。。。
…标准::转发(d)。。。

如果某些东西“导致代码冗余”,则重构出重复的代码。复制构造函数和移动构造函数有着根本不同的用途;移动/非移动赋值运算符也是如此。如果每组运算符都有许多共同的代码,则将其分解。@Lingxi:“通常情况下,这两个重载的实现非常相似,这会导致代码冗余。”大约99%的情况下,这两个函数“非常相似”"实现时,您正在执行的是元素级复制/移动。如果您有一个成员需要特殊的复制/移动处理,那么该成员应该在内部处理。@NicolBolas是的,这可以通过转发引用来完成。但是签名太可接受了。@Lingxi:我不是这个意思。我的意思是您使用
=default
用于复制和移动构造函数。如果成员需要特殊的复制/移动处理,则该成员应属于具有自己的特殊复制/移动处理的类型。因此,如果您的类型存储了表示文件句柄的整数,则不应存储
int
;您应存储具有移动构造的仅移动类型转移句柄所有权的tor/assignment运算符。外部类应该只使用默认值。@Nicolas同意。但是,我遇到的问题不是标准的复制/移动构造函数/赋值运算符。请注意,
T
U
可能是不同的类型。我想
=default
不起作用。
template<class T,class V>
concept Same_d = std::is_same_v<std::decay_t<T>,std::decay_t<U>>;

bool compare_exchange_weak(std::shared_ptr<T>&, Same_d{U}<std::shared_ptr<T>>&& d...
  ... std::forward<U>(d) ...