2017-12-04 6 views
2

に存在します。ビルドシステムとして、私は、現在使用されている標準があるためのUbuntu 16.04上およびWindows 10上のVisual Studio 2017でGCC 5.4でCMakeのを使用するが、私は次のように私はそれを定義した便利なタイプstd::void_tを使用したい:C2386:「void_t」:この名前のシンボルがすでに私は、Windows</strong><strong>上およびLinux</strong><strong>上に構築されることを意図している<strong>Qtの</strong>プロジェクトに取り組んでいる現在のスコープ

#if __cplusplus >= 201703L 
#include <type_traits> 
#else 
namespace std { 
template<typename... Ts> struct make_void { typedef void type; }; 
template<typename... Ts> using void_t = typename make_void<Ts...>::type; 
} 
#endif 

私が述べたコンパイラとLinuxでプロジェクトをビルドする場合は、上記の定義が正常に動作しているが、私はWindowsでそれを構築しようとすると、私は次のエラーメッセージ受信:

C2386: 'void_t': a symbol with this name already exists in the current scope 
U1077: 'C:\PROGRA~2\MICROS~4\2017\ENTERP~1\VC\Tools\MSVC\1411~1.255\bin\HostX64\x64\cl.exe' : return code '0x2' 
U1077: '"C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Tools\MSVC\14.11.25503\bin\HostX64\x64\nmake.exe"' : return code '0x2' 
U1077: '"C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Tools\MSVC\14.11.25503\bin\HostX64\x64\nmake.exe"' : return code '0x2' 

トップレベルCMakeのファイルを次のようにC++標準を設定します。

set(CMAKE_CXX_STANDARD 14) 
set(CMAKE_CXX_STANDARD_REQUIRED ON) 
set(CMAKE_CXX_EXTENSIONS OFF) 

は、私は標準がに設定されている場合のVisual Studio 2017がstd::void_tのために文句ない理由を理解していません。これは正常な動作なのですか?私は正しく表示された方法でstd名前空間を汚染してもエラーは発生しないと誤って予期していますか? Visual Studio 2017で生成されたこれらのエラーをどのように克服できますか?


編集:私は事前に定義されたマクロ__cplusplusの値に依存することunexpected resultsを引き起こす可能性があることに気づきました。 This質問も__cplusplusマクロを目指しています。

答えて

2

CMAKE_CXX_STANDARDオプションは、現在のVisual Studioに限られた効果を持っています。

要求されたバージョンの標準を指定するためにコマンドラインスイッチ-stdを提供するgccまたはclangと異なり、Visual C++は常にすべての最新機能を一度に提供します。 2015年版(Update 3)でのみ、より新しい言語機能のオプトインメカニズムを提供することを目的とした/std optionが導入されました。

残念ながら、これはgccやclangの同等のものほど成熟していないため、期待していない機能がまだ残っている可能性があります。

4

これは正常な動作ですか?示された方法でstd名前空間を汚染してもエラーは発生しないと間違っていると思いますか?

標準ライブラリはnamespace stdを所有しています。あなたは特定の特定の状況においてのみそれを追加することができます。ブランドの新しいタイプを宣言することは、そのような状況の1つではありません。 namespace stdを汚していると、ある時点で問題が発生することがあります。

この特定のケースでは、あなた自身のvoid_tを標準ライブラリバージョンよりも使用することで、本当に失うものはありません。それは動作します。だからそれをやりなさい。それとも、本当に別の名前空間に、どちらか一方を持って、標準的なものを使用したい場合:

namespace xstd { 
#if __cplusplus >= 201703L 
    using std::void_t; 
#else  
    template<typename... Ts> struct make_void { typedef void type; }; 
    template<typename... Ts> using void_t = typename make_void<Ts...>::type; 
#endif 
} 

// use xstd::void_t throughout 
関連する問題

 関連する問題