久久久久久久av_日韩在线中文_看一级毛片视频_日本精品二区_成人深夜福利视频_武道仙尊动漫在线观看

這個(gè)可變參數(shù)模板代碼有什么作用?

What does this variadic template code do?(這個(gè)可變參數(shù)模板代碼有什么作用?)
本文介紹了這個(gè)可變參數(shù)模板代碼有什么作用?的處理方法,對(duì)大家解決問(wèn)題具有一定的參考價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧!

問(wèn)題描述

限時(shí)送ChatGPT賬號(hào)..
template <class F, class... Args> 
void for_each_argument(F f, Args&&... args) { 
    [](...){}((f(std::forward<Args>(args)), 0)...); 
}

它最近在 isocpp.org 上沒(méi)有解釋.

It was recently featured on isocpp.org without explanation.

推薦答案

簡(jiǎn)短的回答是它做得不是很好".

The short answer is "it does it not very well".

它對(duì)每個(gè) args... 調(diào)用 f,并丟棄返回值.但這樣做的方式在許多情況下會(huì)導(dǎo)致意外行為,這是不必要的.

It invokes f on each of the args..., and discards the return value. But it does so in a way that leads to unexpected behavior in a number of cases, needlessly.

代碼沒(méi)有順序保證,如果給定 Argf 返回值有一個(gè)重載的 operator,它可以有不幸的副作用.

The code has no ordering guarantees, and if the return value of f for a given Arg has an overloaded operator, it can have unfortunate side effects.

有一些空白:

[](...){}(
  (
    f(std::forward<Args>(args)), 0
  )...
);

我們將從內(nèi)部開始.

f(std::forward(args)) 是一個(gè)不完整的語(yǔ)句,可以用 ... 展開.展開時(shí),它將在 args 之一上調(diào)用 f.調(diào)用此語(yǔ)句 INVOKE_F.

f(std::forward<Args>(args)) is an incomplete statement that can be expanded with a .... It will invoke f on one of args when expanded. Call this statement INVOKE_F.

(INVOKE_F, 0)f(args) 的返回值,應(yīng)用operator, 然后0>.如果返回值沒(méi)有覆蓋,則丟棄 f(args) 的返回值并返回 0.調(diào)用此 INVOKE_F_0.如果 f 返回一個(gè)帶有覆蓋 operator,(int) 的類型,這里就會(huì)發(fā)生不好的事情,如果該運(yùn)算符返回一個(gè)非 POD 類型的類型,你可以得到有條件地支持"行為稍后.

(INVOKE_F, 0) takes the return value of f(args), applies operator, then 0. If the return value has no overrides, this discards the return value of f(args) and returns a 0. Call this INVOKE_F_0. If f returns a type with an overriden operator,(int), bad things happen here, and if that operator returns a non-POD-esque type, you can get "conditionally supported" behavior later on.

[](...){} 創(chuàng)建一個(gè)將 C 風(fēng)格的可變參數(shù)作為其唯一參數(shù)的 lambda.這與 C++11 參數(shù)包或 C++14 可變參數(shù) lambda 不同.將非 POD 類型的類型傳遞給 ... 函數(shù)可能是非法的.調(diào)用這個(gè)HELPER

[](...){} creates a lambda that takes C-style variadics as its only argument. This isn't the same as C++11 parameter packs, or C++14 variadic lambdas. It is possibly illegal to pass non-POD-esque types to a ... function. Call this HELPER

HELPER(INVOKE_F_0...) 是一個(gè)參數(shù)包擴(kuò)展.在調(diào)用 HELPERoperator() 的上下文中,這是一個(gè)合法的上下文.參數(shù)的評(píng)估未指定,并且由于 HELPER INVOKE_F_0... 的簽名可能應(yīng)該只包含普通的舊數(shù)據(jù)(在 C++03 中),或者更多特別是 [expr.call]/p7 說(shuō):(通過(guò)@TC)

HELPER(INVOKE_F_0...) is a parameter pack expansion. in the context of invoking HELPER's operator(), which is a legal context. The evaluation of arguments is unspecified, and due to the signature of HELPER INVOKE_F_0... probably should only contain plain old data (in C++03 parlance), or more specifically [expr.call]/p7 says: (via @T.C)

傳遞具有非平凡復(fù)制構(gòu)造函數(shù)、非平凡移動(dòng)構(gòu)造函數(shù)或非平凡析構(gòu)函數(shù)的類類型(第 9 條)的潛在評(píng)估參數(shù),沒(méi)有相應(yīng)的參數(shù),有條件地支持實(shí)現(xiàn)定義的語(yǔ)義.

Passing a potentially-evaluated argument of class type (Clause 9) having a nontrivial copy constructor, a non-trivial move constructor, or a non-trivial destructor, with no corresponding parameter, is conditionally-supported with implementation-defined semantics.

所以這段代碼的問(wèn)題是順序未指定并且它依賴于行為良好的類型特定的編譯器實(shí)現(xiàn)選擇.

So the problems of this code is that the order is unspecified and it relies on well behaved types or specific compiler implementation choices.

我們可以修復(fù)operator,問(wèn)題如下:

We can fix the operator, problem as follows:

template <class F, class... Args> 
void for_each_argument(F f, Args&&... args) { 
  [](...){}((void(f(std::forward<Args>(args))), 0)...); 
}

然后我們可以通過(guò)在初始化器中擴(kuò)展來(lái)保證順序:

then we can guarantee order by expanding in an initializer:

template <class F, class... Args> 
void for_each_argument(F f, Args&&... args) { 
  int unused[] = {(void(f(std::forward<Args>(args))), 0)...}; 
  void(unused); // suppresses warnings
}

但是當(dāng) Args... 為空時(shí),上面會(huì)失敗,所以添加另一個(gè) 0:

but the above fails when Args... is empty, so add another 0:

template <class F, class... Args> 
void for_each_argument(F f, Args&&... args) { 
  int unused[] = {0, (void(f(std::forward<Args>(args))), 0)...}; 
  void(unused); // suppresses warnings
}

并且編譯器沒(méi)有充分的理由不從存在中消除 unused[],同時(shí)仍然在 args...f> 按順序.

and there is no good reason for the compiler to NOT eliminate unused[] from existance, while still evaluated f on args... in order.

我的首選變體是:

template <class...F>
void do_in_order(F&&... f) { 
  int unused[] = {0, (void(std::forward<F>(f)()), 0)...}; 
  void(unused); // suppresses warnings
}

它接受 nullary lambdas 并一次運(yùn)行一個(gè),從左到右.(如果編譯器可以證明順序無(wú)關(guān)緊要,則可以隨意亂序運(yùn)行它們).

which takes nullary lambdas and runs them one at a time, left to right. (If the compiler can prove that order does not matter, it is free to run them out of order however).

然后我們可以通過(guò)以下方式實(shí)現(xiàn)上述內(nèi)容:

We can then implement the above with:

template <class F, class... Args> 
void for_each_argument(F f, Args&&... args) { 
  do_in_order( [&]{ f(std::forward<Args>(args)); }... );
}

將奇怪的擴(kuò)展"放在一個(gè)孤立的函數(shù)中(do_in_order),我們可以在其他地方使用它.我們也可以編寫類似工作的 do_in_any_order,但使 any_order 清晰:然而,除非極端原因,在參數(shù)包擴(kuò)展中以可預(yù)測(cè)的順序運(yùn)行代碼可以減少意外和盡量減少頭痛.

which puts the "strange expansion" in an isolated function (do_in_order), and we can use it elsewhere. We can also write do_in_any_order that works similarly, but makes the any_order clear: however, barring extreme reasons, having code run in a predictable order in a parameter pack expansion reduces surprise and keeps headaches to a minimum.

do_in_order 技術(shù)的一個(gè)缺點(diǎn)是并非所有編譯器都喜歡它——擴(kuò)展包含整個(gè)子語(yǔ)句的語(yǔ)句的參數(shù)包并不是他們期望必須做的事情.

A downside to the do_in_order technique is that not all compilers like it -- expanding a parameter pack containing statement that contains entire sub-statements is not something they expect to have to do.

這篇關(guān)于這個(gè)可變參數(shù)模板代碼有什么作用?的文章就介紹到這了,希望我們推薦的答案對(duì)大家有所幫助,也希望大家多多支持html5模板網(wǎng)!

【網(wǎng)站聲明】本站部分內(nèi)容來(lái)源于互聯(lián)網(wǎng),旨在幫助大家更快的解決問(wèn)題,如果有圖片或者內(nèi)容侵犯了您的權(quán)益,請(qǐng)聯(lián)系我們刪除處理,感謝您的支持!

相關(guān)文檔推薦

Difference between std::reference_wrapper and simple pointer?(std::reference_wrapper 和簡(jiǎn)單指針的區(qū)別?)
Difference between const. pointer and reference?(常量之間的區(qū)別.指針和引用?)
How to access the contents of a vector from a pointer to the vector in C++?(c++ - 如何從指向向量的指針訪問(wèn)向量的內(nèi)容?)
Meaning of *amp; and **amp; in C++(*amp; 的含義和**amp;在 C++ 中)
Why can#39;t I do polymorphism with normal variables?(為什么我不能對(duì)普通變量進(jìn)行多態(tài)?)
Dereferencing deleted pointers always result in an Access Violation?(取消引用已刪除的指針總是會(huì)導(dǎo)致訪問(wèn)沖突?)
主站蜘蛛池模板: 中文字幕免费视频 | 久草网址 | 国产91在线 | 亚洲 | 日韩精品免费视频 | 国产精品视频在线免费观看 | 欧州一区二区三区 | 超碰97人人人人人蜜桃 | jizz在线看片 | 麻豆一区 | 毛片黄片免费看 | 精品视频久久久 | 看片一区| 亚洲国产成人在线 | 97综合在线| 日本高清视频在线播放 | 日本免费网 | 亚洲欧美一区二区三区情侣bbw | 成人精品一区二区 | xxx国产精品视频 | 精品乱子伦一区二区三区 | av影音资源 | 国产人成精品一区二区三 | 欧美中国少妇xxx性高请视频 | 久久久久国产一区二区三区不卡 | 亚洲一区二区三区免费 | 99视频入口| 亚洲一区二区综合 | 亚洲一区 | 在线成人 | 精品视频一区二区 | 亚洲精品黑人 | www.国产91 | 国产日韩电影 | 午夜小视频免费观看 | 精品国产鲁一鲁一区二区张丽 | 91麻豆精品国产91久久久更新资源速度超快 | 看羞羞视频 | 国产在线观看 | 日本中文字幕日韩精品免费 | 成人网在线观看 | 99热国产精品 |