我一直試圖從這里了解 , 的實作std::reference_wrapper,如下所示:
namespace detail {
template <class T> constexpr T& FUN(T& t) noexcept { return t; }
template <class T> void FUN(T&&) = delete;
}
template <class T>
class reference_wrapper {
public:
// types
typedef T type;
// construct/copy/destroy
template <class U, class = decltype(
detail::FUN<T>(std::declval<U>()),
std::enable_if_t<!std::is_same_v<reference_wrapper, std::remove_cvref_t<U>>>()
)>
constexpr reference_wrapper(U&& u) noexcept(noexcept(detail::FUN<T>(std::forward<U>(u))))
: _ptr(std::addressof(detail::FUN<T>(std::forward<U>(u)))) {}
reference_wrapper(const reference_wrapper&) noexcept = default;
// assignment
reference_wrapper& operator=(const reference_wrapper& x) noexcept = default;
// access
constexpr operator T& () const noexcept { return *_ptr; }
constexpr T& get() const noexcept { return *_ptr; }
template< class... ArgTypes >
constexpr std::invoke_result_t<T&, ArgTypes...>
operator() ( ArgTypes&&... args ) const {
return std::invoke(get(), std::forward<ArgTypes>(args)...);
}
private:
T* _ptr;
};
盡管這里和這里已經討論了 std::reference_wrapper 的實作,但沒有一個討論我感到困惑的建構式實作。我的困惑是: 1.) 建構式是一個模板函式,采用U與模板類 param 不同的型別 param( ) T。我已經看到一個類的成員函式是模板函式,并且取決于不同的型別引數然后是模板類的型別引數,但我想不出它在這里是如何作業的。還有一個相關的問題在這里,但我不能與我的困惑有關吧。2.)我看到建構式中的第二個型別引數進一步用于過濾某些東西,但我不明白如何detail::FUN<T>(std::declval<U>()) 被評估。
有人可以解釋一下嗎?
編輯:這是從microsoft.docs添加的示例。該示例的一個片段是:
int i = 1;
std::reference_wrapper<int> rwi(i); // A.1
rwi.get() = -1;
std::cout << "i = " << i << std::endl; //Prints -1
有了 reference_wrapper 和 from 的實作,reference_wrapper A.1的建構式是怎么呼叫的?假設detail::FUN<T>(std::declval<U>()將被呼叫detail::FUN<T>(std::declval<int>(),應該是由于deleted多載而導致的替換失敗(假設std::declval<int>將被讀取為對 int 的右值參考)。我在這里錯過了什么?
uj5u.com熱心網友回復:
U&&在這種情況下,當您想要“轉發參考”的行為時,可以使用這種技術,但同時限制可以系結到它的內容。
扣除T由下面提供的扣導向輔助。的detail::FUN<T>(std::declval<U>())是有保證的是,當構造被禁止U被推斷為是右值參考,通過選擇洗掉的過載,并產生了無效的表達。如果U是另一個參考包裝器,它也會被禁用,在這種情況下應該選擇復制建構式。
以下是一些有效和無效reference_wrapper的示例:
int i = 1;
// OK: FUN<int>(std::declval<int&>()) is valid
std::reference_wrapper<int> rwi(i);
// error: forming pointer to reference
std::reference_wrapper<int&> rwi2(i);
// OK, uses deduction guide to find T = int
std::reference_wrapper rwi3(i);
std::reference_wrapper rwi4( i);
// error: cannot deduce T, since there is no deduction guide for
// rvalue reference to T
std::reference_wrapper rwi5(std::move(i));
// error: substitution failure of FUN<int>(int&&)
std::reference_wrapper<int> rwi6(std::move(i));
std::reference_wrapper<int> rwi7(i );
std::reference_wrapper<int> rwi8(i i);
std::reference_wrapper<int> rwi9(2);
如您所見,對已洗掉的呼叫FUN<T>(T&&)僅在最后 4 種情況下起作用:當您顯式指定T,但嘗試從右值構造時。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/403233.html
標籤:
