C++17部分特性整理

C++17部分特性整理

1、使 static_assert 的文本信息可選

  • 簡(jiǎn)化和 static_assert的使用,c++17起,消息 可選
static_assert ( 布爾常量表達(dá)式 , 消息 )   (C++11 起)  
static_assert ( 布爾常量表達(dá)式 )   (C++17 起)

2侣诺、刪除 trigraphs

  • 刪除三元轉(zhuǎn)移字符
  • 最初因?yàn)閕so646的標(biāo)準(zhǔn),部分國(guó)家打不出# ~ ^ 之類的字符氧秘,使用??加一個(gè)字符的方式替代年鸳,c++11中不建議使用trigraphs,c++17中被棄用
Trigraph Equivalent
??= #
??/ \
??' ^
??( [
??) ]
??! ` `
??< {
??> }
??- ~

3丸相、在模板參數(shù)中允許使用 typename(作為替代類)

template<typename T> class my_array {};

// 兩個(gè)類型模板形參和一個(gè)模板模板形參:
template<typename K, typename V, template<typename> typename C = my_array>
class Map
{
    C<K> key;
    C<V> value;
};

4、braced-init-list自動(dòng)推導(dǎo)的新規(guī)則

  • 采用大括號(hào)的形式初始化auto變量膳算,可以自動(dòng)完成類型的推導(dǎo)
  • 規(guī)則braced-init-list 左側(cè)只能是單個(gè)元素
auto x1 = { 1, 2 }; // decltype(x1) is std::initializer_list<int> 【initializer_list用于表示特定類型值的數(shù)組】
auto x2 = { 1, 2.0 }; // error: cannot deduce element type座硕,會(huì)對(duì)右側(cè)常量進(jìn)行類型檢查
auto x3{ 1, 2 }; // error: not a single element
auto x4 = { 3 }; // decltype(x4) is std::initializer_list<int>
auto x5{ 3 }; // decltype(x5) is int
  • std::initializer_list的簡(jiǎn)單介紹【列表初始化】

    std::vector<int>a{1,2,3,4,5};
    std::vector<int>a = {1,2,3,4,5};
    //vecotr可以使用列表進(jìn)行初始化,因?yàn)閧1,2,3,4,5}被推導(dǎo)為std::initializer_list<int>類型涕蜂,vector的構(gòu)造函數(shù)對(duì)std::initializer_list<int>類型進(jìn)行特化和對(duì)賦值運(yùn)算符的重載進(jìn)行了特化华匾。
    
    

    [圖片上傳失敗...(image-bff33a-1584675555477)]

5、嵌套命名空間

  • 嵌套命名空間定義:namespace A::B::C { ... } 等價(jià)于 namespace A { namespace B { namespace C { ... } } }机隙。
  • namespace A::B::inline C { ... } 等價(jià)于 namespace A::B { inline namespace C { ... } }蜘拉。(c++20)inline 可出現(xiàn)于除首個(gè)以外的每個(gè)命名空間名之前

6、允許命名空間和枚舉器的屬性

1有鹿、格式

枚舉格式:

enumerator: identifier attribute-specifier-seqopt

作用域格式:

  • original-namespace-definition:
    inlineopt namespace attribute-specifier-seqopt identifier { namespace-body }
  • extension-namespace-definition:
    inlineopt namespace attribute-specifier-seqopt original-namespace-name { namespace-body }
  • unnamed-namespace-definition:
    inlineopt namespace attribute-specifier-seqopt { namespace-body }

2旭旭、屬性格式

[[attr]] [[attr1, attr2, attr3(args)]]

3、語(yǔ)法

  • [[ 屬性列表 ]] (c++11)
  • [[ using 屬性命名空間 :屬性列表]] (c++17)

4葱跋、屬性實(shí)例

(未找到有關(guān)namesapce和enum相關(guān)的實(shí)例持寄,以函數(shù)屬性列表的使用舉例)

[[gnu::always_inline]] [[gnu::hot]] [[gnu::const]] [[nodiscard]]
inline int f(); // 聲明 f 帶四個(gè)屬性
 
[[gnu::always_inline, gnu::const, gnu::hot, nodiscard]]
int f(); // 同上,但使用含有四個(gè)屬性的單個(gè)屬性說(shuō)明符
 
// C++17:
[[using gnu : const, always_inline, hot]] [[nodiscard]]
int f[[gnu::always_inline]](); // 屬性可出現(xiàn)于多個(gè)說(shuō)明符中
 
int f() { return 0; }
 
int main() {}

7娱俺、新的標(biāo)準(zhǔn)屬性:

[[fallthrough]]:

  • 僅可應(yīng)用到空語(yǔ)句以創(chuàng)建直落語(yǔ)句(fallthrough statement):[[fallthrough]];稍味。

  • 直落語(yǔ)句僅可用于 switch 語(yǔ)句中,其中待執(zhí)行的下個(gè)語(yǔ)句是該 switch 語(yǔ)句的帶 case 或 default 標(biāo)號(hào)的語(yǔ)句矢否。

  • 指示從前一標(biāo)號(hào)直落是有意的仲闽,而在發(fā)生直落時(shí)給出警告的編譯器不應(yīng)診斷它

    void f(int n) {
      void g(), h(), i();
      switch (n) {
        case 1:
        case 2:
          g();
         [[fallthrough]];
        case 3: // 直落時(shí)不警告
          h();
        case 4: // 編譯器可在發(fā)生直落時(shí)警告【實(shí)際運(yùn)行結(jié)果并未發(fā)生警告】
          if(n < 3) {
              i();
              [[fallthrough]]; // OK
          }
          else {
              return;
          }
        case 5:
          [[fallthrough]]; // 非良構(gòu)脑溢,無(wú)后繼的 case 或 default 標(biāo)號(hào)
      }
    }
    

[[nodiscard]]

  • 出現(xiàn)在函數(shù)聲明僵朗、枚舉聲明或類聲明中
  • 若從并非轉(zhuǎn)型到 void 的棄值表達(dá)式中,調(diào)用聲明為 nodiscard 的函數(shù)屑彻,或調(diào)用按值返回聲明為 nodiscard 的枚舉或類的函數(shù)验庙,則鼓勵(lì)編譯器發(fā)布警告。
struct [[nodiscard]] error_info { };
error_info enable_missile_safety_mode();
void launch_missiles();
void test_missiles() {
   enable_missile_safety_mode(); // 編譯器可在舍棄 nodiscard 值時(shí)發(fā)布警告
   launch_missiles();
}
error_info& foo();
void f1() {
    foo(); // 并非按值返回 nodiscard 類型社牲,無(wú)警告
}

[[maybe_unused]]

  • 抑制針對(duì)未使用實(shí)體的警粪薛,此屬性可出現(xiàn)在下列實(shí)體的聲明中:
  • 若編譯器針對(duì)未使用實(shí)體發(fā)布警告,則對(duì)于任何聲明為 maybe_unused 的實(shí)體抑制該警告搏恤。
[[maybe_unused]] void f([[maybe_unused]] bool thing1,
                        [[maybe_unused]] bool thing2)
{
   [[maybe_unused]] bool b = thing1 && thing2;
   assert(b); // 發(fā)行模式中违寿,assert 在編譯中被去掉,因而未使用 b
              // 無(wú)警告熟空,因?yàn)樗宦暶鳛?[[maybe_unused]]
} // 未使用參數(shù) thing1 與 thing2藤巢,無(wú)警告

9、允許所有非類型模板實(shí)參的常量求值

  • 附:實(shí)例
//隊(duì)列某個(gè)元素或者非靜態(tài)數(shù)據(jù)成員的地址息罗,對(duì)于非類型模板參數(shù)是不合法的掂咒;
template<int* p> class X { };

int a[10];
struct S { int m; static int s; } s;

X<&a[2]> x3; // error: address of array element
X<&s.m> x4;  // error: address of non-static member
X<&s.s> x5;  // error: &S::s must be used OK: address of static member
X<&S::s> x6; // OK: address of static member

10、折疊表達(dá)式及在可變長(zhǎng)參數(shù)模板中的使用

折疊表達(dá)式

格式

  • 一元左折疊(pack op ...)
  • 一元右折疊(... op pack)
  • 二元右折疊(pack op ... op I)
  • 二元左折疊(I op ... op pack)

展開

  • 一元左折疊展開:((E1 op E2) op ...) op EN
  • 一元右折疊展開:E1 op (... op (EN-1 op EN))
  • 二元右折疊展開:E1 op (... op (EN-1 op (EN op I)))
  • 二元左折疊展開:(((I op E1) op E2) op ...) op EN

注意

  • 若用作 init 或 pack 的表達(dá)式在頂層優(yōu)先級(jí)低于轉(zhuǎn)型淮椰,則它可以加括號(hào):
template<typename ...Args>
int sum(Args&&... args) {
//    return (args + ... + 1 * 2); // 錯(cuò)誤:優(yōu)先級(jí)低于轉(zhuǎn)型的運(yùn)算符
    return (args + ... + (1 * 2)); // OK
}
  • 二元折疊表達(dá)式兩邊的操作數(shù)只能有一個(gè)未展開的的參數(shù)包
template<typename... Args>
  bool f(Args... args) { 
    return (true + ... + args); // OK
  } 

template<typename... Args>
  bool f(Args... args) { 
    return (args && ... && args); // error: both operands contain unexpanded parameter packs
  }

變長(zhǎng)參數(shù)模板參數(shù)解包方法

之前解包方法:

# include <iostream >
template < typename T0 >
void printf (T0 value ) {
    std :: cout << value << std :: endl ;
}
template < typename T, typename ... Args >
void printf (T value , Args ... args ) {
    std :: cout << value << std :: endl ;
    printf ( args ...) ;
}
int main () {
    printf (1, 2, "123 ", 1.1) ;
    return 0;
}

基于constexpr的解包方法[c++17]

template < typename T0, typename ... T>
void magic(T0 t0, T... t) {
    std::cout << t0 << std::endl;
    if constexpr (sizeof ...(t) > 0) magic(t ...);
}

11实柠、if constexpr關(guān)鍵字的使用

  • C++11 引入了constexpr 關(guān)鍵字贾富,它將表達(dá)式或函數(shù)編譯為常量镀钓;

  • C++17 將constexpr 這個(gè)關(guān)鍵字引入到if 語(yǔ)句中架曹,允許在代碼中聲明常量蜓竹,把這一特性引入到條件判斷中去术羔,讓代碼在編譯時(shí)就完成分支判斷姑蓝;

    template < typename T>
    auto print_type_info ( const T& t) {
      if constexpr (std :: is_integral <T >:: value ) {
          return t + 1;
      } 
        else {
          return t + 0.001; 
        }
    }
    int main () {
      std :: cout << print_type_info (5) << std :: endl ;
      std :: cout << print_type_info (3.14) << std :: endl ;
    }
    

    編譯時(shí)展現(xiàn)形式:

    int print_type_info ( const int & t) {
      return t + 1;
    }
    double print_type_info ( const double & t) {
      return t + 0.001;
    }
    

12膝蜈、結(jié)構(gòu)化綁定聲明

1刨裆、格式

  • attr(可選) cv-auto ref-運(yùn)算符(可選) [ 標(biāo)識(shí)符列表 ] = 表達(dá)式 ;
  • attr(可選) cv-auto ref-運(yùn)算符(可選) [ 標(biāo)識(shí)符列表 ] {表達(dá)式 };
  • attr(可選) cv-auto ref-運(yùn)算符(可選) [ 標(biāo)識(shí)符列表 ] (表達(dá)式 );
名稱 解釋
attr 任意數(shù)量的屬性的序列
cv-auto 可有 cv 限定的 auto 類型說(shuō)明符
ref-運(yùn)算符 &&& 之一
標(biāo)識(shí)符列表 此聲明所引入的各標(biāo)識(shí)符的逗號(hào)分隔的列表
表達(dá)式 頂層沒(méi)有逗號(hào)運(yùn)算符的表達(dá)式(文法上為賦值表達(dá)式),且具有數(shù)組或非聯(lián)合類之一的類型彬檀。

2帆啃、綁定情況

2.1綁定到數(shù)組

int a[2] = {1,2};
 
auto [x,y] = a; // 創(chuàng)建 e[2],復(fù)制 a 到 e窍帝,然后 x 指代 e[0]努潘,y 指代 e[1]
auto& [xr, yr] = a; // xr 指代 a[0],yr 指代 a[1]

2.2綁定到元組式類型

float x{};
char  y{};
int   z{};
 
std::tuple<float&,char&&,int> tpl(x,std::move(y),z);
const auto& [a,b,c] = tpl;
// a 指名指代 x 的結(jié)構(gòu)化綁定坤学;decltype(a) 為 float&
// b 指名指代 y 的結(jié)構(gòu)化綁定疯坤;decltype(b) 為 char&&
// c 指名指代 tpl 的第 3 元素的結(jié)構(gòu)化綁定;decltype(c) 為 const int

2.3綁定到數(shù)組成員

struct S {
    int x1 : 2;
    volatile double y1;
};
S f();
 
auto [x, y] = f(); // x 是標(biāo)識(shí) 2 位位域的 int 左值
                   // y 是 volatile double 左值
//根據(jù)測(cè)試結(jié)果 auto [x, y]前不能加cv操作符深浮,否則編譯不過(guò):由于tupule_size無(wú)法識(shí)別

3压怠、注意示項(xiàng)

1、標(biāo)志符的數(shù)量必須等于數(shù)組元素或元組元素或者結(jié)構(gòu)體中非靜態(tài)數(shù)據(jù)成員的數(shù)量飞苇;

13菌瘫、if 和 switch 語(yǔ)句中的變量初始化

  • 在if和switch中可以完成初始化,

    • if ( init-statement <u>opt</u> condition ) statement
    • if ( init-statement <u>opt</u> condition ) statement else statement
    • switch ( init-statement <u>opt</u> condition ) statement

表達(dá)式展開格式如下:

  • if ( init-statement condition ) statement 展開格式如下:

{

? init-statement

? if ( condition ) statement

}

  • if ( init-statement condition ) statement else *statemen 展開格式如下:

{

? init-statement

? if ( condition ) statement else statement

}

  • switch ( init-statement condition ) statement 展開格式如下:

{

*init-statement*   

? switch ( condition ) statement

}

實(shí)例

實(shí)例1

before

status_code foo() {  
    {     
        status_code c = bar();    
        if (c != SUCCESS) {      
            return c;     
        }   
    }  
    // ... 
}

after

status_code foo() {  
    if (status_code c = bar();c != SUCCESS) {      
        return c;     
    } 
    // ... 
}

實(shí)例2

before

void safe_init() { 
    {    
        std::lock_guard<std::mutex> lk(mx_);
        if (v.empty()){       
            v.push_back(kInitialValue);    
        }  
    }  
    // ... 
}

after

void safe_init() { 
    if (std::lock_guard<std::mutex> lk(mx_);v.empty()){       
            v.push_back(kInitialValue);    
     }   
    // ... 
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市布卡,隨后出現(xiàn)的幾起案子雨让,更是在濱河造成了極大的恐慌,老刑警劉巖忿等,帶你破解...
    沈念sama閱讀 218,546評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件栖忠,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡贸街,警方通過(guò)查閱死者的電腦和手機(jī)庵寞,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)薛匪,“玉大人捐川,你說(shuō)我怎么就攤上這事〉氨玻” “怎么了属拾?”我有些...
    開封第一講書人閱讀 164,911評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵将谊,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我渐白,道長(zhǎng)尊浓,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,737評(píng)論 1 294
  • 正文 為了忘掉前任纯衍,我火速辦了婚禮栋齿,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘襟诸。我一直安慰自己瓦堵,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,753評(píng)論 6 392
  • 文/花漫 我一把揭開白布歌亲。 她就那樣靜靜地躺著菇用,像睡著了一般。 火紅的嫁衣襯著肌膚如雪陷揪。 梳的紋絲不亂的頭發(fā)上惋鸥,一...
    開封第一講書人閱讀 51,598評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音悍缠,去河邊找鬼卦绣。 笑死,一個(gè)胖子當(dāng)著我的面吹牛飞蚓,可吹牛的內(nèi)容都是我干的滤港。 我是一名探鬼主播,決...
    沈念sama閱讀 40,338評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼趴拧,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼溅漾!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起八堡,我...
    開封第一講書人閱讀 39,249評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤樟凄,失蹤者是張志新(化名)和其女友劉穎聘芜,沒(méi)想到半個(gè)月后兄渺,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,696評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡汰现,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,888評(píng)論 3 336
  • 正文 我和宋清朗相戀三年挂谍,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片瞎饲。...
    茶點(diǎn)故事閱讀 40,013評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡口叙,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出嗅战,到底是詐尸還是另有隱情妄田,我是刑警寧澤俺亮,帶...
    沈念sama閱讀 35,731評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站疟呐,受9級(jí)特大地震影響脚曾,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜启具,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,348評(píng)論 3 330
  • 文/蒙蒙 一本讥、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧鲁冯,春花似錦拷沸、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至跨扮,卻和暖如春勤庐,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背好港。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工愉镰, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人钧汹。 一個(gè)月前我還...
    沈念sama閱讀 48,203評(píng)論 3 370
  • 正文 我出身青樓丈探,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親拔莱。 傳聞我的和親對(duì)象是個(gè)殘疾皇子碗降,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,960評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • (三)文學(xué)類文本閱讀(本題共3小題,15分) 閱讀下面的文字塘秦,完成7~9 題讼渊。 秋唱 ...
    傲氣沖天925閱讀 1,401評(píng)論 0 0
  • 誤會(huì)了,在此特別登報(bào)聲明尊剔!居然要登報(bào)了爪幻?有這么聲勢(shì)浩大的事嗎?值得你如此大動(dòng)干戈须误,也不怕引起人家笑話挨稿,當(dāng)然有。因?yàn)?..
    昭昭_21e3閱讀 235評(píng)論 0 0
  • 論文紙片盒子 03FRACTURE FLOW RATE ESTIMATION USING MACHINE LEAR...
    亻令仃忝鉂閱讀 640評(píng)論 0 0
  • 繼承extends 單一繼承京痢,只能有一個(gè)父類 方法重寫 返回值類型奶甘,方法名,參數(shù)類型祭椰,順序臭家,個(gè)數(shù)都要與父類相同疲陕。訪...
    ssss2閱讀 200評(píng)論 0 0
  • 什么樣的女子,才可以活成歲月深處的那一抹嫣紅钉赁,有一個(gè)自給自足的小宇宙鸭轮,任憑時(shí)光流轉(zhuǎn),不傾橄霉,不頹窃爷,不必依然裝扮粉嫩,...
    宋西坡閱讀 254評(píng)論 5 7