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

編譯器如何處理編譯時(shí)分支?

What do compilers do with compile-time branching?(編譯器如何處理編譯時(shí)分支?)
本文介紹了編譯器如何處理編譯時(shí)分支?的處理方法,對大家解決問題具有一定的參考價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧!

問題描述

我以if/else"情況為例,有時(shí)可以在編譯時(shí)解決(例如,當(dāng)涉及靜態(tài)值時(shí),參見 ).將下面的答案改編為其他類型的靜態(tài)分支(例如,多個(gè)分支或多標(biāo)準(zhǔn)分支)應(yīng)該很簡單.請注意,使用模板元編程的編譯時(shí)分支不是這里的主題.

I took the "if/else" case as an example that can sometimes be resolved at compile time (eg when static values are involved, cf <type_traits>). Adapting the answers below to other types of static branching (eg, multiple branches or multi-criteria branches) should be straightforward. Note that compile-time branching using template-meta programming is not the topic here.

在這樣的典型代碼中

#include <type_traits>

template <class T>
T numeric_procedure( const T& x )
{
    if ( std::is_integral<T>::value )
    {
        // Integral types
    }
    else
    {
        // Floating point numeric types
    }
}

當(dāng)我稍后在代碼中定義特定模板類型時(shí),編譯器會優(yōu)化 if/else 語句嗎?

will the compiler optimize the if/else statement out when I define specific template types later on in my code?

一個(gè)簡單的替代方法是編寫如下內(nèi)容:

A simple alternative would be to write something like this:

#include <type_traits>

template <class T>
inline T numeric_procedure( const T& x )
{
    return numeric_procedure_impl( x, std::is_integral<T>() );
}

// ------------------------------------------------------------------------

template <class T>
T numeric_procedure_impl( const T& x, std::true_type const )
{
    // Integral types
}

template <class T>
T numeric_procedure_impl( const T& x, std::false_type const )
{
    // Floating point numeric types
}

這些解決方案在性能方面是否存在差異?是否有任何非主觀理由可以說一個(gè)比另一個(gè)好?是否有其他(可能更好)的解決方案來處理編譯時(shí)分支?

Is there a difference in terms of performance between these solutions? Is there any non-subjective grounds for saying that one is better than the other? Are there other (possibly better) solutions to deal with compile-time branching?

推薦答案

TL;DR

有幾種方法可以根據(jù)模板參數(shù)獲得不同的運(yùn)行時(shí)行為.在這里,性能不應(yīng)該是您的主要關(guān)注點(diǎn),而應(yīng)該是靈活性和可維護(hù)性.在所有情況下,各種瘦包裝器和常量條件表達(dá)式都將在任何合適的編譯器上進(jìn)行優(yōu)化以用于發(fā)布版本.下面是各種權(quán)衡的小總結(jié)(靈感來自@AndyProwl 的這個(gè)答案).

TL;DR

There are several ways to get different run-time behavior dependent on a template parameter. Performance should not be your primary concern here, but flexibility and maintainability should. In all cases, the various thin wrappers and constant conditional expressions will all be optimized away on any decent compiler for release builds. Below a small summary with the various tradeoffs (inspired by this answer by @AndyProwl).

您的第一個(gè)解決方案是簡單的運(yùn)行時(shí)if:

Your first solution is the simple run-time if:

template<class T>
T numeric_procedure(const T& x)
{
    if (std::is_integral<T>::value) {
        // valid code for integral types
    } else {
        // valid code for non-integral types,
        // must ALSO compile for integral types
    }
}

它既簡單又有效:任何合適的編譯器都會優(yōu)化掉死分支.

It is simple and effective: any decent compiler will optimize away the dead branch.

有幾個(gè)缺點(diǎn):

  • 在某些平臺 (MSVC) 上,常量條件表達(dá)式會產(chǎn)生虛假的編譯器警告,然后您需要忽略或忽略該警告.
  • 但更糟糕的是,在所有符合標(biāo)準(zhǔn)的平臺上,if/else 語句的兩個(gè)分支都需要為所有類型T 實(shí)際編譯,即使如果其中一個(gè)分支已知不被采用.如果 T 根據(jù)其性質(zhì)包含不同的成員類型,那么您將在嘗試訪問它們時(shí)立即收到編譯器錯(cuò)誤.
  • on some platforms (MSVC), a constant conditional expression yields a spurious compiler warning which you then need to ignore or silence.
  • But worse, on all conforming platforms, both branches of the if/else statement need to actually compile for all types T, even if one of the branches is known not to be taken. If T contains different member types depending on its nature, then you will get a compiler error as soon as you try to access them.

您的第二種方法稱為標(biāo)記調(diào)度:

Your second approach is known as tag-dispatching:

template<class T>
T numeric_procedure_impl(const T& x, std::false_type)
{
    // valid code for non-integral types,
    // CAN contain code that is invalid for integral types
}    

template<class T>
T numeric_procedure_impl(const T& x, std::true_type)
{
    // valid code for integral types
}

template<class T>
T numeric_procedure(const T& x)
{
    return numeric_procedure_impl(x, std::is_integral<T>());
}

它工作正常,沒有運(yùn)行時(shí)開銷:臨時(shí) std::is_integral() 和對單行輔助函數(shù)的調(diào)用都將在任何體面的平臺上進(jìn)行優(yōu)化.

It works fine, without run-time overhead: the temporary std::is_integral<T>() and the call to the one-line helper function will both be optimized way on any decent platform.

主要(次要 IMO)缺點(diǎn)是您有一些帶有 3 個(gè)而不是 1 個(gè)函數(shù)的樣板.

The main (minor IMO) disadvantage is that you have some boilerplate with 3 instead of 1 function.

與標(biāo)簽調(diào)度密切相關(guān)的是 SFINAE(替換失敗不是錯(cuò)誤)

Closely related to tag-dispatching is SFINAE (Substitution failure is not an error)

template<class T, class = typename std::enable_if<!std::is_integral<T>::value>::type>
T numeric_procedure(const T& x)
{
    // valid code for non-integral types,
    // CAN contain code that is invalid for integral types
}    

template<class T, class = typename std::enable_if<std::is_integral<T>::value>::type>
T numeric_procedure(const T& x)
{
    // valid code for integral types
}

這與標(biāo)簽調(diào)度具有相同的效果,但工作方式略有不同.它不是使用參數(shù)推導(dǎo)來選擇合適的輔助重載,而是直接操作主函數(shù)的重載集.

This has the same effect as tag-dispatching but works slightly differently. Instead of using argument-deduction to select the proper helper overload, it directly manipulates the overload set for your main function.

缺點(diǎn)是,如果您不確切知道整個(gè)重載集是什么(例如,使用模板繁重的代碼,ADL 可能會從關(guān)聯(lián)的命名空間中引入更多的重載)不考慮).與標(biāo)簽分派相比,基于二元決策以外的任何選擇的選擇要復(fù)雜得多.

The disadvantage is that it can be a fragile and tricky way if you don't know exactly what the entire overload set is (e.g. with template heavy code, ADL could pull in more overloads from associated namespaces you didn't think of). And compared to tag-dispatching, selection based on anything other than a binary decision is a lot more involved.

另一種方法是使用帶有函數(shù)應(yīng)用運(yùn)算符的類模板助手并對其進(jìn)行部分特化

Another approach is to use a class template helper with a function application operator and partially specialize it

template<class T, bool> 
struct numeric_functor;

template<class T>
struct numeric_functor<T, false>
{
    T operator()(T const& x) const
    {
        // valid code for non-integral types,
        // CAN contain code that is invalid for integral types
    }
};

template<class T>
struct numeric_functor<T, true>
{
    T operator()(T const& x) const
    {
        // valid code for integral types
    }
};

template<class T>
T numeric_procedure(T const& x)
{
    return numeric_functor<T, std::is_integral<T>::value>()(x);
}

如果您想進(jìn)行細(xì)粒度控制和最少的代碼重復(fù)(例如,如果您還想專注于大小和/或?qū)R,但僅針對浮點(diǎn)類型),這可能是最靈活的方法.部分模板特化給出的模式匹配非常適合此類高級問題.與標(biāo)記分派一樣,任何合適的編譯器都會優(yōu)化輔助函子.

This is probably the most flexible approach if you want to have fine-grained control and minimal code duplication (e.g. if you also want to specialize on size and/or alignment, but say only for floating point types). The pattern matching given by partial template specialization is ideally suited for such advanced problems. As with tag-dispatching, the helper functors are optimized away by any decent compiler.

如果您只想專注于單個(gè)二進(jìn)制條件,主要缺點(diǎn)是樣板文件稍大.

The main disadvantage is the slightly larger boiler-plate if you only want to specialize on a single binary condition.

這是重啟 之前失敗的 static if(在 D 編程語言中使用)

This is a reboot of failed earlier proposals for static if (which is used in the D programming language)

template<class T>
T numeric_procedure(const T& x)
{
    if constexpr (std::is_integral<T>::value) {
        // valid code for integral types
    } else {
        // valid code for non-integral types,
        // CAN contain code that is invalid for integral types
    }
}

與您的運(yùn)行時(shí) if 一樣,所有內(nèi)容都在一個(gè)地方,但這里的主要優(yōu)點(diǎn)是 else 分支將被編譯器完全刪除已知不會被采取.一個(gè)很大的優(yōu)勢是您可以將所有代碼保留在本地,并且不必像在標(biāo)簽分派或部分模板特化中那樣使用很少的輔助函數(shù).

As with your run-time if, everything is in one place, but the main advantage here is that the else branch will be dropped entirely by the compiler when it is known not to be taken. A great advantage is that you keep all code local, and do not have to use little helper functions as in tag dispatching or partial template specialization.

Concepts-Lite 是一個(gè) 即將推出的技術(shù)規(guī)范,計(jì)劃成為下一個(gè)主要 C++ 版本(C++1z,z==7 為最佳猜測)的一部分.

Concepts-Lite is an upcoming Technical Specification that is scheduled to be part of the next major C++ release (C++1z, with z==7 as the best guess).

template<Non_integral T>
T numeric_procedure(const T& x)
{
    // valid code for non-integral types,
    // CAN contain code that is invalid for integral types
}    

template<Integral T>
T numeric_procedure(const T& x)
{
    // valid code for integral types
}

這種方法替換了 templateclasstypename 關(guān)鍵字.> 帶有概念名稱的括號,描述代碼應(yīng)該適用的類型系列.它可以看作是標(biāo)簽調(diào)度和 SFINAE 技術(shù)的概括.一些編譯器(gcc、Clang)對此功能有實(shí)驗(yàn)性支持.Lite 形容詞指的是失敗的 Concepts C++11 提案.

This approach replaces the class or typename keyword inside the template< > brackets with a concept name describing the family of types that the code is supposed to work for. It can be seen as a generalization of the tag-dispatching and SFINAE techniques. Some compilers (gcc, Clang) have experimental support for this feature. The Lite adjective is referring to the failed Concepts C++11 proposal.

這篇關(guān)于編譯器如何處理編譯時(shí)分支?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網(wǎng)!

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

相關(guān)文檔推薦

Can I use if (pointer) instead of if (pointer != NULL)?(我可以使用 if (pointer) 而不是 if (pointer != NULL) 嗎?)
Checking for NULL pointer in C/C++(在 C/C++ 中檢查空指針)
Math-like chaining of the comparison operator - as in, quot;if ( (5lt;jlt;=1) )quot;(比較運(yùn)算符的數(shù)學(xué)式鏈接-如“if((5<j<=1)))
Difference between quot;if constexpr()quot; Vs quot;if()quot;(“if constexpr()之間的區(qū)別與“if())
C++, variable declaration in #39;if#39; expression(C++,if 表達(dá)式中的變量聲明)
if (cin gt;gt; x) - Why can you use that condition?(if (cin x) - 為什么你可以使用那個(gè)條件?)
主站蜘蛛池模板: 91精品国产91久久久久久三级 | 国产亚洲精品精品国产亚洲综合 | 久久久久久久久久久久亚洲 | 色综合天天天天做夜夜夜夜做 | 色综合中文 | 久久在线| 欧美精品成人一区二区三区四区 | 毛片在线看片 | 天天干天天色 | 激情五月婷婷综合 | 日日av | 一本一道久久a久久精品综合 | 日韩精品一区二区三区中文在线 | 亚洲成人播放器 | 欧美激情久久久久久 | 国产一级片免费在线观看 | 九九久久久 | 国产激情视频在线免费观看 | 欧美性区 | 亚洲小视频在线播放 | 成人网在线| 久久久久久久国产精品视频 | 国产精品亚洲成在人线 | 毛片网在线观看 | 色吧久久 | 日本福利视频免费观看 | 日韩在线看片 | 精品成人佐山爱一区二区 | 91精品国产一二三 | 99久久婷婷国产综合精品 | 一级黄色毛片a | 中文字幕第二区 | 日日摸日日爽 | 国产欧美一区二区在线观看 | 日韩精品专区在线影院重磅 | 91精品国产91久久综合桃花 | 精品国产91亚洲一区二区三区www | 日本a网站 | 久久久91| 久久久久久久久一区 | www成人免费视频 |