2016-12-06 11 views
6

次のプログラムはC++ 11対応ですか?もしそうなら、それを引き起こす特定のMSVCバグについて知っていますか?および/または可能な回避策?オーバーロードされたテンプレート関数のMSVC2015 decltypeパラメータタイプ

#include <iostream> 

struct A {}; 
struct B {}; 

constexpr A aaa = {}; 
constexpr B bbb = {}; 

template <typename T> 
void foo(T, decltype(aaa)) { std::cout << "a"; } 

template <typename T> 
void foo(T, decltype(bbb)) { std::cout << "b"; } 
//^C2995 'void foo(T,unknown-type)': function template has already been defined 

int main() 
{ 
    foo(0, aaa); 
    foo(0, bbb); 
} 

実際の型はdecltypeに代入されている場合、それは動作しますが、実際にはこれらの型が再現すると、私は彼らのために別名を持つことが希望されない、あまりにも複雑です。

+0

コンパイルをgcc/clangでうまくいけば、C++ 11に準拠していないものも見えません。 – Jarod42

答えて

4

次のマイナーな変更を加えた私の作品(VS 2015/V140):

#include <iostream> 

struct A {}; 
struct B {}; 

constexpr A aaa = {}; 
constexpr B bbb = {}; 

using A_type = decltype(aaa); 
using B_type = decltype(bbb); 

template <typename T> 
void foo(T, A_type) { std::cout << "a"; } 

template <typename T> 
void foo(T, B_type) { std::cout << "b"; } 

int main() 
{ 
    foo(0, aaa); 
    foo(0, bbb); 
} 

しかし、この変形は、(それを作るのかわからない)同じエラーが得られます

template <typename T> 
struct TypeWrapper { 
    using type = T; 
}; 

template <typename T> 
void foo(T, typename TypeWrapper<decltype(aaa)>::type) { std::cout << "a"; } 

template <typename T> 
void foo(T, typename TypeWrapper<decltype(bbb)>::type) { std::cout << "b"; } 
+0

私はMSVCがエイリアスのテキスト置換を行っていると思った。私はそれが働いているのに驚いています。私は以前、これらの「不明型」に関連するいくつかの厄介なバグに取り組んでいました。エイリアスが動作していることを知っておいてよかったです。 –

+0

@GuillaumeRacicot:型エイリアスは新しい別の型とはみなされません。むしろあなたがそれを持ち上げたので、私はむしろそれが自分自身を働かせないと思っています。どうやら、コンパイラは 'decltype()'構造を混乱させるのは型そのものではなく、コンパイラが正しく処理できる別のコンテキストに置いてあります。少なくともそれは私の現在の理論です。 –

+0

明らかにこれもうまくいきます: 'template wrap = T;を使用して、' wrap 'をパラメータリストに入れてください。 –

関連する問題