2016-04-17 14 views
1

私は可変テンプレートを試していて、奇妙な問題が発生しました。入れ子クラスの可変テンプレート

template<int v0, int ...Vs> 
class Foo 
{ 
public: 
    template<typename nested = void, 
     typename = void> 
    class Reduce 
    { 
    public: 
     static int const value = v0; 
    }; 

    template<typename nested> 
    class Reduce<nested, 
     typename std::enable_if<0<sizeof...(Vs)>::type> 
    { 
    public: 
     static int const value = v0 + Foo<Vs...>::template Reduce<>::value; 
    }; 
}; 

このコードはテンプレートクラスでネストされたテンプレートクラスは完全に専門的なことができないので、私はネストされたダミーのテンプレートパラメータを挿入し、エラーメッセージ

//example code 
int s = Foo<0,1,2,3,4,5>::Reduce<>::value; 
std::cout << s << std::endl; 

error: incomplete type 'F<5>::Reduce<>' used in nested name specifier 

をもたらします。実際に私はコンパイラが不完全な型について不平を言う理由を理解していない。
私は

template<int v0, int ...Vs> 
class Reduced 
{ 
public: 
    static int const value = v0 + Reduce<Vs...>::value; 
}; 

template<int v0> 
class Reduced<v0> 
{ 
public: 
    static int const value = v0; 
}; 

template<int v0, int ...Vs> 
class Foo 
{ 
public: 
    class Reduce 
    { 
    public: 
     static int const value = Reduced<v0, Vs...>::value; 
    }; 
}; 

その作業のに可変長のものを変更するが、他の1がない理由を私は知りません。コンパイラがそのエラーを投げている理由は何ですか?手伝ってくれてありがとう。

答えて

1

これは[temp.expl.spec](強調鉱山)C++標準§14.7.3/ P16明示的な特化の引用に起因する:明示的な特殊化宣言で

クラス テンプレートのメンバまたは名前空間スコープに表示されるメンバテンプレートの場合、 メンバテンプレートおよびその囲むクラステンプレートの一部は、 未指定、のままである可​​能性があります。ただし、宣言は明示的に は、その囲むクラステンプレート が明示的に特殊化されていない場合でも、クラスメンバーテンプレートを特化します。囲むクラスも同様に特化されてFooない限り、あなたは専門的なタイプFoo<int...>::Reduced<>のオブジェクトを持つことはできませんされて

template<int v0, int ...Vs> 
class Foo { 
public: 
    class Reduce { 
    public: 
    static int const value = v0 + Foo<Vs...>::Reduce::value; 
    }; 
}; 

template<int v0> 
class Foo<v0> { 
public: 
    class Reduce { 
    public: 
    static int const value = v0; 
    }; 
}; 

Live Demo

それとも、入れ子になったクラスを取り除くことができます::

は、次の方法でこれを修正することができ

template<int v0, int ...Vs> 
class Foo { 
public: 
    static int const value = v0 + Foo<Vs...>::value; 
}; 

template<int v0> 
class Foo<v0> { 
public: 
    static int const value = v0; 
}; 

Live Demo

C++ 17折り畳み式を導入しています。問題が解決しない

template<int v0, int ...Vs> 
class Foo { 
public: 
    static const int s = v0 + (Vs + ...); 
}; 

Live Demo

+0

このアプローチでは、テンプレート引数 'nested'はまったく必要ありません。 さらに、私はFooクラスの特殊化を避けるのが好きです。実際の使用例では、他の多くのものが含まれているため、私は専門化のために再実装したくありません。 – Feuerteufel

+0

@Feuerteufelはい、テンプレート引数はこのアプローチでは余計です。 – 101010

+1

@Feuerteufel私はあなたに合った編集チェックを追加しました。 – 101010

1
typename std::enable_if<0<sizeof...(Vs)>::type 

不平等チェックを括弧で囲む必要があります。

typename std::enable_if< (0 < sizeof...(Vs)) >::type 
+0

いいえ、:折り目式を使用するとだけ行って、あなたがやりたいことができます。パーサーがブラケットと演算子として区別できない場合、私は驚くでしょう。 – Feuerteufel

関連する問題