这接近于代码审查/最佳实践,但是……这样做是否合理?
// A metafunction to map T -> T but std::reference_wrapper<T> -> T&:
template <typename T> struct RefWrapperToRef { using type = T; };
template <typename T> struct RefWrapperToRef<std::reference_wrapper<T>> { using type = T&; };
// A metafunction like std::remove_reference but std::reference_wrapper<T> -> T.
template <typename T> struct RemoveRefAndRefWrapper {
using type = std::remove_reference_t<typename RefWrapperToRef<T>::type>;
};
template <typename T>
struct S {
static_assert(not std::is_rvalue_reference_v<T>, "There may be a place for it, but it's dangerous.");
T x;
// Allow construction from a universal reference by forwarding.
template <typename U>
explicit S(U&& x) : x(std::forward<U>(x)) {
static_assert(std::is_same_v<std::remove_cv_t<typename RemoveRefAndRefWrapper<U>::type>,
std::remove_cv_t<typename RemoveRefAndRefWrapper<T>::type>>);
static_assert(not std::is_reference_v<T> or std::is_lvalue_reference_v<typename RefWrapperToRef<U>::type>);
}
};
template <typename T>
S(T) -> S<typename RefWrapperToRef<T>::type>;
也就是说,如果你有int x
并且打电话S(std::ref(x))
,我们会假设你想要一个S<int&>
. 这看起来优雅、简单、明确,但又有点神奇。