簡體   English   中英

如何選擇基於C ++版本的函數實現

[英]How to choose function implementation based on C++ version

我已經重新定義了某些C ++函數對象(STL函數),以便為它們提供constexpr operator()。 我需要這些功能來在編譯時進行評估,以用於模板元編程。 C ++ 14為STL功能庫提供了constexpr等效項。 目前,我正在使用C ++ 11編譯代碼,但最終可能會升級到C ++ 14。 如何實現這些功能,以便如果升級到C ++ 14,它將自動從STL中選擇功能對象,而不是我的自定義實現。
到目前為止,這是我的方法:

namespace foo {
 template <class T = void>
 struct less {
   constexpr bool operator()(T const& lhs, T const& rhs) const { 
     return lhs < rhs;
   }
 };
}

編輯 :我知道如果我只是用std為我的命名空間加上別名,就可以使用__cplusplus來完成。 但是,這將是一個糟糕的解決方案,因為我會污染其他所有實例的名稱空間foo。

選項,其方法可能對工作的影響最小,對代碼的影響最小,首先:

  • 使用編譯器的包含文件路徑選擇標題的不同版本。

  • 編譯器版本嗅探和條件編譯(例如#ifdef )。

  • 批發代碼編輯,可能是自動化的。

編譯器嗅探非常脆弱,但是很常見。

僅檢查__cplusplus的值通常是不夠的。


例如,使用編譯器的include路徑,您首先定義一個頭文件<relops.hpp> ,它根據C ++ 14功能,默認實現來定義或命名所有內容,並將其放置在常規頭文件頭目錄中。

並通過編譯器的include路徑(例如,對於g ++的CPATH和對於Visual C ++的INCLUDE ),如果特定的編譯器需要,則將其定向為首先在其他目錄中查找<relops.h>以獲取系統特定的頭文件。

並且此<relops.h>會定義事物本身,就像在您提供的代碼中一樣。


隨着條件編譯你反而會確定基於宏如編譯器和版本__cplusplus_MSC_VER__GNUC__ ,一些適用於Mac,可能更多。 您將因此定義一些符號,例如IS_CPP14 然后,您將使用#if IS_CPP14#else#endif

您可以使用基於__cplusplus基於預處理器的解決方案,而不會污染foo名稱空間,具體如下:

namespace foo {
#if __cplusplus < 201402L
 template <class T = void>
 struct less {
   constexpr bool operator()(T const& lhs, T const& rhs) const { 
     return lhs < rhs;
   }
 };
#else
  using std::less;
#endif
}

它為14之前的C ++版本定義了foo::less的自定義版本,並為新的C ++版本創建了std::less的別名(仍可用作foo::less )。

(常量201402L來自標准本身。要求C ++ 14的編譯器將__cplusplus至少設置__cplusplus值)。

在編譯器僅部分支持C ++ 14的情況下,即使該部分支持包括constexpr限定的std::less::operator() ,上述代碼也可能導致您less使用自定義實現。 顯然,這對於Visual Studio的最新版本是正確的。 我建議這甚至不值得擔心; 無論如何,都應該內聯對該函數的調用,並且當您使用適當兼容的C ++ 14編譯器進行編譯時,您將獲得所需的確切(編譯級)行為。 或者,您可以擴展預處理器邏輯(即檢查編譯器特定的宏),以識別已知具有足夠一致性的特定編譯器版本。

暫無
暫無

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

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