1

GCCからMSVCにコードを移植する際、このあいまいな問題に直面しました。<variadic template> Visual Studioでデフォルト値のコンパイルエラーが発生したテンプレートパラメータ

template <typename T> 
struct Foo; 

template <template <typename...> typename Container, typename Arg> 
struct Foo<Container<Arg>> { 
    using arg_t = Arg; 
}; 

template <typename X> 
struct A {}; 

template <typename X, typename Y = void> 
struct B {}; 

template <typename X, typename Y = void, typename Z = void> 
struct C {}; 

int main() { 
    typename Foo<A<int>>::arg_t a; 
    typename Foo<B<int>>::arg_t b; 
    typename Foo<C<int>>::arg_t c; 
    return 0; 
} 

我々は、デフォルト値(実際のユースケースは、例えばstd::unique_ptrである)を有する第2のテンプレートパラメータから始まるテンプレートクラスの最初の引数を抽出するFoo形質を使用:

は、次のスニペットを考えます。 ClangとGCCはこのスニペットを完全に処理しますが、MSVC(Visual Studio 17に付属するもの)は非常に明白なコンパイルエラーをスローします。

答えて

1

GCCとClangはデフォルトのテンプレートパラメータを何とか処理して、A<X, Y=void><template <typename...> typename Bar, typename X> Bar<X>インターフェイスで受け入れられるようにしました。一方、MSVCはそうではありません。標準であるかGCC/Clang拡張であるかは不明です。とにかく、の解決策は、残りのパラメータと一致するようにダミーvariadicパラメータを追加することです。

template <typename T> 
struct Foo; 

template <template <typename...> typename Container, 
      typename Arg, typename... MsvcWorkaround> 
struct Foo<Container<Arg, MsvcWorkaround....>> { 
    using arg_t = Arg; 
}; 

template <typename X> 
struct A {}; 

template <typename X, typename Y = void> 
struct B {}; 

template <typename X, typename Y = void, typename Z = void> 
struct C {}; 

int main() { 
    typename Foo<A<int>>::arg_t a; 
    typename Foo<B<int>>::arg_t b; 
    typename Foo<C<int>>::arg_t c; 
    return 0; 
} 

コンパイラのエラーから問題を理解するのは難しく、解決策を見つけることができませんでした。そのため私は私のものを共有したいのです。

+0

2つの警告:この回避策では、複数のデフォルトではないパラメータ( 'std :: map 'など)を持つクラステンプレートは元のコードとは異なり、デフォルト以外のクラステンプレートは許可されません元のテンプレートとは異なります。 – oisyn

関連する問題