1. 程式人生 > >C++20 要來了!

C++20 要來了!

640?wx_fmt=gif

C++的新標準又雙叒叕要到來了,是的,C++20要來了!

640?wx_fmt=jpeg

圖片來源:udemy.com

幾周前,C++標準委會歷史上規模最大的一次會議(180人蔘會)在美國San Diego召開,這次的會議上討論確定哪些特性要加入到C++20中,哪些特性可能加入到C++20中。在明年二月份的會議當中將正式確定所有的C++20特性。

這次會議討論的提案也是非常之多,達到了創紀錄的274份,C++20的新特性如果要一一列出的話將是一份長長的清單,因此本文將只評論大部分確定要加入和可能加入到C++20的重要特性,讓讀者對C++的未來和演進趨勢有一個基本的瞭解。

C++20中可能增加哪些重要特性,下面這個圖可以提供一個參考。

640?wx_fmt=png

下面是本文將評論的將進入和可能進入C++20的重要特性:

  • Concepts

  • Ranges

  • Modules

  • Coroutines

  • Reflection

接下來讓我們慢慢揭開C++20的面紗,看看這些特性到底是什麼樣的,它們解決了什麼問題。


640?wx_fmt=png

Concepts


在談Concepts之前我想先介紹一下Concepts提出的背景和原因。眾所周知,因為C++的模版和模版元具備非常強大的泛型抽象能力並且是zero overhead,所以模版在C++中備受推崇,大獲成功,在各種C++庫(如STL)中被廣泛使用。

然而,模版程式設計還存在一些問題,比如有些模版的程式碼寫起來比較困難,讀起來比較難懂,尤其是編譯出錯的時候,那些糟糕的讓人摸不著頭腦的錯誤提示讓人頭疼。因此,C++之父Bjarne Stroustrup很早就希望對模版做一些改進,讓C++的模版程式設計變得簡單好寫,錯誤提示更明確。他早在1987年就開始做這方面的嘗試了。

640?wx_fmt=jpeg

C++之父Bjarne Stroustrup

具體思路就是給模版引數加一些約束,這些約束相比之前的寫法具有更強的表達能力和可讀性,會簡化C++的泛型模版程式碼的編寫。

所以Concepts的出現主要是為了簡化泛型程式設計,一個Concept就是一個編譯期判斷,用於約束模版引數,Concepts則是這些編譯期判斷的合集。下面通過一個例子來展示Concepts是如何簡化模版程式設計的。

    template<typename T>
    class B {

    public:
      template<typename ToString = T>
      typename std::enable_if_t<std::is_convertible<ToString, std::string>::value, std::string>
      to_string() const {
        return "Class B<>";
      }
    };

    B<size_t> b1;                             // OK
    std::cout << b1.to_string() << std::endl// Compile ERROR!

    B<std::string> b2;                        // OK
    std::cout << b2.to_string() << std::endl// OK!

比如有這樣一個類B,我們呼叫它的成員函式tostring時,對T型別進行限定,即限定T型別是std::string的可轉換型別,這樣做的目的是為了更安全,能在編譯期就能檢查錯誤。這裡通過C++14的std::enableif_t來對T進行限定,但是長長的enableift看起來比較冗長繁瑣,頭重腳輕。來看看用Concepts怎麼寫這個程式碼的。

    template<typename T>
    concept CastableToString = requires(T a) {
      { a } -> std::string;
    };

    template<typename T>
    class D {
    public:
      std::string to_string() const requires CastableToString<T> {
        return "Class D<>";
      }
    };

可以看到,requires CastableToString比之前長長的enableift要簡潔不少,程式碼可讀性也更好,CastableToString就是一個Concept,一個限定T為能被轉換為std::string型別的Concept,通過requires相連線,語義上也更明確了,而且這個Concept還可以複用。

Concepts的這個語法也可能在最終的C++20中有少許不同,有可能還會變得更簡潔,現在語法有幾個候選版本,還沒最終投票確定。


640?wx_fmt=png

Ranges


相比STL,Ranges是更高一層的抽象,Ranges對STL做了改進,它是STL的下一代。為什麼說Ranges是STL的未來?雖然STL在C++中提供的容器和演算法備受推崇和廣泛被使用,但STL一直存在兩個問題:

  • STL強制你必須傳一個begin和end迭代器用來遍歷一個容器;

  • STL演算法不方便組合在一起。

STL必須傳迭代器,這個迭代器僅僅是輔助你完成遍歷序列的技術細節,和我們的函式功能無關,大部分時候我們需要的是一個range,代表的是一個比迭代器更高層的抽象。

那麼Ranges到底是什麼呢?Ranges是一個引用元素序列的物件,在概念上類似於一對迭代器。這意味著所有的STL容器都是Ranges。在Ranges裡我們不再傳迭代器了,而是傳range。比如下面的程式碼:

STL寫法:

    std::vector<int> v{12};
    std::sort(v.begin(), v.end());

Ranges寫法:

    std::sort(v);

STL有時候不方便將一些演算法組合在一起,來看一個例子:

    std::vector<int> v{12345};

    std::vector<int> event_numbers;
    std::copy_if(v.begin(), v.end(), std::back_inserter(event_numbers), [](int i){ return i % 2 == 0;});

    std::vector<int> results;
    std::transform(event_numbers.begin(), event_numbers.end(), std::back_inserter(event_numbers), [](int i){ return i * 2;});

    for(int n : results){
        std::cout<<n<<' ';
    }
    //最終會輸出 4 8

上面這個例子希望得到vector中的偶數乘以2的結果,需求很簡單,但是用STL寫起來還是有些冗長繁瑣,中間還定義了兩個臨時變數。如果用Ranges來實現這個需求,程式碼就會簡單得多。

    auto results = v | ranges::view::filter([](int i){ return i % 2 == 0; })
                     | ranges::view::transform([](int i){ return i * 2; });

用Concetps我們可以很方便地將演算法組合在一起,寫法更簡單,語義更清晰,並且還可以實現延遲計算避免了中間的臨時變數,效能也會更好。

Concepts從設計上改進了之前STL的兩個問題,讓我們的容器和演算法變得更加簡單好用,還容易組合。


640?wx_fmt=png

Modules


一直以來C++一直通過引用標頭檔案方式使用庫,而其他90年代以後的語言比如Java、C#、Go等語言都是通過import包的方式來使用庫。現在C++決定改變這種情況了,在C++20中將引入Modules,它和Java、Go等語言的包的概念是類似的,直接通過import包來使用庫,再也看不到標頭檔案了。

為什麼C++20不再希望使用#include方式了?因為使用標頭檔案方式存在不少問題,比如有include很多模版的標頭檔案將大大增加編譯時間,程式碼生成物也會變大。而且引用標頭檔案方式不利於做一些C++庫和元件的管理工具,尤其是對於一些雲環境和分散式環境下不方便管理,C++一直缺一個包管理工具,這也是C++被吐槽得很多的地方,現在C++20 Modules將改變這一切。

Modules在程式中的結構如下圖:

640?wx_fmt=png

上面的圖中,每個方框表示一個翻譯單元,存放在一個檔案裡並且可以被獨立編譯。每個Module由Module介面和實現組成,介面只有一份,實現可以有多份。

Modules介面和實現的語法:

    export module module_name;

    module module_name;

使用Modules:

    import module_name;

Modules允許你匯出類,函式,變數,常量和模版等等。

接下來看一個使用Modules的例子:

    import std.vector// #include <vector>
    import std.string// #include <string>
    import std.iostream; // #include <iostream>
    import std.iterator; // #include <iterator >
    int main() {
        using namespace std;
        vector<string> v = {
            "Socrates""Plato""Descartes""Kant""Bacon"
        };
        copy(begin(v), end(v), ostream_iterator<string>(cout"\n"));
    }

可以看到不用再include了,直接去import需要用到的Modules即可,是不是有種似曾相識的感覺呢。曾看到一個人說如果C++支援了Modules他就會從Java迴歸到C++,也說明這個特性也是非常受關注和期待的。


640?wx_fmt=png

Coroutines


很多語言提供了Coroutine機制,因為Coroutine可以大大簡化非同步網路程式的編寫,現在C++20中也要加入協程了(樂觀估計C++20加入,悲觀估計在C++23中加入)。

如果不用協程,寫一個非同步的網路程式是不那麼容易的,以boost.asio的非同步網路程式設計為例,我們需要注意的地方很多,比如非同步事件完成的回撥函式中需要保證呼叫物件仍然存在,如何構建非同步回撥鏈條等等,程式碼比較複雜,而且出了問題也不容易除錯。而協程給我們提供了對非同步程式設計優雅而高效的抽象,讓非同步程式設計變得簡單!

C++ Courotines中增加了三個新的關鍵字:co_await,co_yield和co_return,如果一個函式體中有這三個關鍵字之一就變成Coroutine了。

co_await用來掛起和恢復一個協程,co_return用來返回協程的結果,co_yield返回一個值並且掛起協程。

下面來看看如何使用它們。

寫一個lazy sequence:

    generator<int> get_integers( int start=0int step=1 ) {
      for (int current=start; current+= step)
        co_yield current;
    }

    for(auto n : get_integers(05)){
      std::cout<<n<<" ";
    }
    std::cout<<'\n';

上面的例子每次呼叫get_integers,只返回一個整數,然後協程掛起,下次呼叫再返回一個整數,因此這個序列不是即時生成的,而是延遲生成的。

接下來再看一下co_wait是如何簡化非同步網路程式的編寫的:

    char data[1024];
    for (;;)
    {
      std::size_t n = co_await socket.async_read_some(boost::asio::buffer(data), token);
      co_await async_write(socket, boost::asio::buffer(data, n), token);
    }

這個例子僅僅用了四行程式碼就完成了非同步的echo,非常簡潔!co_await會在非同步讀完成之前掛起協程,在非同步完成之後恢復協程繼續執行,執行到async_write時又會掛起協程直到非同步寫完成,非同步寫完成之後繼續非同步讀,如此迴圈。如果不用協程程式碼會比較繁瑣,需要像這樣寫:

    void do_read()
    {
      auto self(shared_from_this());
      socket_.async_read_some(boost::asio::buffer(data_, max_length),
        [this, self](boost::system::error_code ec, std::size_t length)
         {
           if (!ec)
           {
             do_write(length);
           }
         });
      }

    void do_write(std::size_t length)
    {
      auto self(shared_from_this());
      boost::asio::async_write(socket_, boost::asio::buffer(data_, length),
        [this, self](boost::system::error_code ec, std::size_t /*length*/)
        {
          if (!ec)
          {
            do_read();
          }
        });
    }

可以看到,不使用協程來寫非同步程式碼的話,需要構建非同步的回撥鏈,需要保持非同步回撥的安全性等等。而使用協程可以大大簡化非同步網路程式的編寫。


640?wx_fmt=png

Reflection


C++中一直缺少反射功能,其他很多語言如Java、C#都具備執行期反射功能。反射可以用來做很多事情:比如做物件的序列化,把物件序列化為JSON、XML等格式,以及ORM中的實體對映,還有RPC遠端過程(方法)呼叫等,反射是應用程式中非常需要的基礎功能。現在C++終於要提供反射功能了,C++20中可會將反射作為實驗庫,在C++23中正式加入到標準中。

在反射還沒有進入到C++標準之前,有很多人做了一些編譯期反射的庫,比如purecpp社群開源的序列化引擎iguana,以及ORM庫ormpp,都是基於編譯期反射實現的。然後,非語言層面支援的反射庫存在種種不足之處,比如在實現上需要大量使用模版元和巨集、不能訪問私有成員等問題。

相關推薦

C++20

C++的新標準又雙叒叕要到來了,是的,C++20要來了! 圖片來源:udemy.com 幾周前,C++標準委會歷史上規模最大的一次會議(180人蔘會)在美國San Diego召開,這次的會議上討論確定哪些特性要加入到C++20中,哪些特性可能加入到C++

我的 Python 網路爬蟲直播分享

開篇之前先提一下上週日的事情。 上週日的時候我參加了北京站的 PyCon China 2018 開發者大會,PyCon 大家知道的吧!就是 Python 界最大的技術開發者大會,會上會有很多 Python 開發者分享自己的相關開發經驗,開發者主要來自歐美國家,而 PyCon China 就是中國區的 PyC

BBR_v2.0真的

  昨天google在BBR論壇上釋出了,BBR演算法小組的最新進展。連結如下   修改的內容主要包括以下一個方面: 提高與基於丟包的擁塞演算法(Reno/Cubic)的共存能力。降低BBR演算法的搶佔性,提高不同演算法之間的公平性。 減小排隊丟包和排隊時延的情況。 這

國內安卓統一推送標準將於3月開啟測試

   2017年,工信部旗下的泰爾實驗室聯合國內多家廠商成立了“安卓統一推送聯盟”,旨在為國內的訊息推送服務建立統一的標準,為終端使用者提供更好的手機使用體驗,為應用開發者更好解決訊息推送需求。2018年3月,統一推送聯盟開始啟動相關標準測試和認定工作。就在前日,《統一推送技術

藍湖:你們的“自動切圖”功能

需要 .cn target iad 兩件 hot 設計圖 sdg style 一般本湖君出來吆喝,必然是要搞大事情~ 繼“自動標註”功能後,藍湖再次解鎖重量級功能——“自動切圖”! 小夥伴們,驚喜不驚喜? ? ?延續“藍湖”老規矩,本“自動切圖”功能: ①同時支持Mac和

2017年過去,2018年

深圳 人工智能 物聯網 it2017年要過去了,2018年來了 ? 說真的,沒感覺, 早已習慣了深圳的每天忙忙碌碌的生活 ; 下班回家的路上,習慣性的打開收音機, 聽著飛揚971的廣播 , 主持人在熱鬧喜慶的音樂中說著元旦提前訂票的事情,心裏才猛的想起,真的一年又要過去了 , 心裏的感覺怎麽有時還停留去年,

亞馬遜的VR購物新體驗網購者的福利

strong ear 百萬 cnblogs 發展 新功能 提前 vr技術 似的   (VR開發網2017年5月5日訊)跟蹤亞馬遜在VR中的工作可能是棘手的,因為公司在似乎涉及多個領域時,響應媒體查詢而聞名遐邇。   該公司正在通過其Lumberyard開發引擎幫助制作VR

Word Level1 + Level2 套餐

表格制作 目錄 標題樣式 郵件合並 腳註與尾註 版本說明:雖以Word2010講解,不過2007和2013等版本也適用。套餐介紹:此套餐可以讓您系統學習整個Word的常用技巧與實用功能,查找與替換、表格制作、圖文混排、長文檔的編輯、郵件合並、窗體與控件等等。從基礎到進階,從簡單短篇文檔的排

淘寶租房哪些行業和職業會“痛哭流涕”?

淘寶租房房價,對幾乎所有人來說,都是心中的痛。雖然各種限制政策層出不窮,但房價還是蹭蹭蹭地網上漲,讓大眾難以承受。因此,對很多漂泊在外務工、上班的人來說,租房幾乎成為唯一途徑。但相比國外租房系統的完善,國內租房市場還處於一個非常混亂的態勢中,負面新聞比比皆是。雖然租房也有很多相關政策,但並沒有從根本上解決問題

福利又又雙叒叕移動端購課專享8折真是“夠”~

手機專享8月31日24點前,通過“51CTO學院”APP購買課程均可享受8折優惠!APP內下載課程還可以倍速播放哦~~~快下載APP吧>>>http://edu.51cto.com/activity/lists/id-10.html(掃描二維碼可直接下載)註:1. iOS App平臺需要單獨

你好,我

鏈接 一定的 計算機 1-1 基礎 平時 介紹 什麽 多少 我的名字是祁金楓,學號是信管141-1425052027。我是來自江蘇宿遷的一位男生。平時的愛好是看書,外出遊玩。喜歡與別人交流自己的感情。在校期間,我通過學習了學校開設的C++和java語言掌握了一定的編程基礎。

共享飛機終於但想普及並不是短時間的事兒

共享飛機共享經濟發展的速度、廣度和深度等,都足以讓業界和大眾瞠目結舌。既有共享單車、共享出行等已經凸顯自身潛力的共享項目,也有共享籃球、共享健身倉、共享雨傘等聚焦於小眾群體的形式。而迅猛發展的共享經濟似乎也變成了奪人眼球的“噱頭”,朝著匪夷所思的方向房展。共享寶馬、共享法拉利之後,共享飛機也終於出現了!就在九

看圖說話,P2P 分享率 90% 以上的 P2P-CDN 服務,

rtmp 一句話 辦公室 raw a-z orm 再看 公司 origin 事情是這樣的:今年年初的時候,公司準備籌劃一個直播項目,在原有的 APP 中嵌入直播模塊,其中的一個問題就是直播加速服務的選取。 老板讓我負責直播加速的產品選型,那天老板把我叫到辦公室,語重心長地說

重點人工智能2018最熱產業將為我們的生活帶來哪些改變?

智慧金融 遠程醫療 智能會議 polycom視頻會議 今年人工智能產業哪些方向最受關註? 當下,人工智能產業出現九大發展熱點領域,分別是芯片、自然語言處理、語音識別、機器學習應用、計算機視覺與圖像、技術平臺、智能無人機、智能機器人、無人駕駛。據新華社北京3月(記者周文林)報道,最新數據顯示,今

Java 11 新功能

html 未來 orm JD lam services frame 引入 世紀 關鍵時刻,第一時間送達!目前 Oracle 已經發布了 Java Development Kit 10,下個版本 JDK 11 也即將發布。本文介紹 Java 11 的新功能。根據Oracle新

.NET Core 2.1

and 圖片 ++ 切換 href 5.7 AS 同事 編譯型 太棒了! .NET Core 2.0正式發布至今已經過去了大半年,這大半年說長不長說短不短,這段時間裏,我是充分地體會到了微軟的誠意,那就是認認真真打造一個優秀的開源平臺。這大半年的時間裏,微軟一直在為.NE

國內第一家Giiso智搜AI寫稿機器人進入商用,新聞媒體行業變天

寫作機器人 編輯機器人 資訊機器人 機器人介入寫稿最早起始於美國老牌報業《華盛頓郵報》。早在2012年,《華盛頓郵報》就啟動了名為“truth teller”的實時新聞核查項目,它能全程記錄新聞報道中的文字、語音等信息,隨後與“打假”數據庫進行對比,一旦發現異常便會發出警報。 從2015年開始,

暴力討債的克星高科技AI催債,效率是職業討債人的雙倍

寫作機器人 編輯機器人 資訊機器人 俗話說,欠債還錢,天經地義,自古以來,“催債”就一直存在。尤記得借貸寶的“裸條門”,山東於歡的“辱母殺人案”,猖獗的“催債行為”讓人膽寒。   催債的方式粗暴駭人   輕則自動軟件電話轟炸騷擾債主,或是發布大量辱罵短信。重則暴力催收,如果百度一下“催收”,能收

會“自己”拍照的AI相機人工智能還會給我們多少驚喜?

傳統 人工智 正在 谷歌 人的 轉載 朋友 出現 人工智能 美好的事物轉瞬即逝,經常拍照的人可能都有過這樣體驗:等拿出相機或手機時,想拍的畫面已經沒有了,隨即只能感嘆一聲。然而,科技發展的速度總會給我們意外的驚喜,就比如“會自動拍照AI相機”的發布。 會自動拍照的相機 前不

世界杯浙江天搜科技賦能B端商家行動已打響

所有 nag 基於 col 多個 學生 假設 浙江天搜科技 人工智 盼了足足四年的2018年世界杯,終於來了!  全球狂歡盛事世界杯揭幕賽,正式開戰!這是無數球迷的狂歡節,當然也是萬千餐飲商家的狂歡節。世界杯為他們帶來了更大的利好消息!  浙江天搜科技股份有限公司(簡稱:浙