簡體   English   中英

C++20 std::common_reference 的目的是什么?

[英]What is the purpose of C++20 std::common_reference?

C++20 引入了std::common_reference 它的目的是什么? 有人可以舉一個使用它的例子嗎?

common_reference來自我努力提出 STL 迭代器的概念化,以適應代理迭代器。

在 STL 中,迭代器有兩種特別感興趣的關聯類型: referencevalue_type 前者是迭代器的operator*的返回類型,而value_type是序列元素的(非常量,非引用)類型。

通用算法通常需要做這樣的事情:

value_type tmp = *it;

...所以我們知道這兩種類型之間一定存在某種關系。 對於非代理迭代器,關系很簡單: reference始終是value_type ,可選 const 和引用限定。 定義InputIterator概念的早期嘗試要求表達式*it可轉換為const value_type & ,並且對於大多數有趣的迭代器來說就足夠了。

我希望 C++20 中的迭代器比這更強大。 例如,考慮一個zip_iterator的需求,它在鎖步中迭代兩個序列。 當您取消引用zip_iterator ,您將獲得兩個迭代器reference類型的臨時pair 因此, zip vector<int>vector<double>將具有以下關聯類型:

zip迭代器的referencepair<int &, double &>
zip迭代器的value_type : pair<int, double>

如您所見,這兩種類型僅通過添加頂級 cv- 和 ref 限定而彼此不相關。 然而讓這兩種類型任意不同感覺是錯誤的。 顯然這里有一些關系。 但是關系是什么,在迭代器上運行的泛型算法可以安全地假設這兩種類型是什么?

C++20 中的答案是,對於任何有效的迭代器類型,代理與否,類型reference &&value_type &共享一個公共引用 換句話說,對於某些迭代器, it有某種類型的CR使以下格式良好:

void foo(CR) // CR is the common reference for iterator I
{}

void algo( I it, iter_value_t<I> val )
{
  foo(val); // OK, lvalue to value_type convertible to CR
  foo(*it); // OK, reference convertible to CR
}

CR是通用參考。 所有算法都可以依賴於這種類型存在的事實,並且可以使用std::common_reference來計算它。

所以,這就是common_reference在 C++20 的 STL 中扮演的角色。 通常,除非您正在編寫通用算法或代理迭代器,否則您可以放心地忽略它。 它在幕后確保您的迭代器履行其合同義務。


編輯:OP 還要求舉個例子。 這有點做作,但想象一下它是 C++20,並且您得到一個R類型的隨機訪問范圍r ,您對此一無所知,並且您想sort范圍進行sort

進一步想象一下,出於某種原因,您想要使用單態比較函數,例如std::less<T> (也許你型擦除的范圍,你也需要鍵入擦除的比較功能,並使其通過一個virtual ?同樣,舒展。)應該什么Tstd::less<T> 為此,您將使用common_reference或根據它實現的助手iter_common_reference_t

using CR = std::iter_common_reference_t<std::ranges::iterator_t<R>>;
std::ranges::sort(r, std::less<CR>{});

即使范圍r有代理迭代器,這也保證有效。

我還沒有在任何可以訪問的編譯器中看到它,但是它只是用於引用的std::common_type 它允許您編寫函數,例如使用公共基類作為返回類型,而與實例化期間的參數順序無關。 這是一個使用-std=c++2astd::common_type與clang11和gcc9一起使用的示例:

#include <iostream>
#include <type_traits>
#include <typeinfo>

template <typename T1, typename T2>
inline typename std::common_type<T1, T2>::type& some_call(int n, T1& t1, T2& t2) {
    return n ? t1 : t2;
}

class A {
public:
    virtual ~A() {}
    virtual void say_hi() {
        std::cerr << "Hi from A!" << std::endl;
    }
};

class B : public A {
public:
    virtual void say_hi() {
        std::cerr << "Hi from B!" << std::endl;
    }
};

int main() {
    A a{}; B b{};
    some_call(0, a, b).say_hi();
    some_call(1, a, b).say_hi();
    some_call(0, b, a).say_hi();
    some_call(1, b, a).say_hi();
    return 0;
}

結果是模板總是A&推斷為返回類型,並將正確調用虛擬函數say_hi

但是,您可以看到,返回類型中的寂寞&被淹沒了,所以我確定主要動機是std::common_reference<T1, T2>::type提供的可讀性超過std::common_type<T1, T2>::type&

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM