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

Collapse overloads for copy and move semantics

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

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

T& operator=(const U&);
T& operator=(U&&);

通常情况下,这两个重载的实现非常相似,这会导致代码冗余。所以我正在考虑将两者合二为一。

我发现实际使用的一种方法是按值传递,让值构造来完成任务。例如,

constexpr atomic_shared_ptr(shared_ptr<T> desired) noexcept;

其中 desired 可以是复制构造的或移动构造的。然而,按值传递并不是万灵药。还是以atomic_shared_ptr为例,

bool compare_exchange_weak(std::shared_ptr<T>&, const std::shared_ptr<T>& d...
bool compare_exchange_weak(std::shared_ptr<T>&, std::shared_ptr<T>&& d...

不同于construction/assignment的情况,根据比较结果,d可能并不总是被复制。如果d是按值传递,总会被复制,而且复制成本不低。

我想到的另一个解决方案是使用转发引用。

template <typename U>
bool compare_exchange_weak(std::shared_ptr<T>&, U&& d...
  ... std::forward<U>(d) ...

不过,这个提法太permissible/tolerable了。

还有其他想法或建议吗?

您可以限制模板:

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) ...

使用 new concept syntax proposal 可以提高可读性:

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) ...