Many methods have overloads for copy and move semantics. For example, construct and assignment from another type,
T(const U&);
T(U&&);
T& operator=(const U&);
T& operator=(U&&);
More often than not, implementations of the two overloads are quite similar, which kind of leads to code redundancy. So I'm considering collapsing the two into one.
One method I find actually in use is to pass by value and let the value construction do the trick. For example,
constexpr atomic_shared_ptr(shared_ptr<T> desired) noexcept;
where desired
may be either copy-constructed or move-constructed. However, pass-by-value is no panacea. Again, take atomic_shared_ptr
as an example,
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...
Unlike the construction/assignment case, depending on the compare result, d
may not always be copied. If d
is passed by value, it will always be copied, and the copy is not cheap.
Another solution I come up with is to use forwarding reference.
template <typename U>
bool compare_exchange_weak(std::shared_ptr<T>&, U&& d...
... std::forward<U>(d) ...
However, this formulation is too permissible/tolerable.
Any other idea or suggestion?
You could constrain the template:
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) ...
With the new concept syntax proposal it could be more readable:
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) ...