6

非型のテンプレート引数と非型のテンプレート パラメーターを使用して、型をテンプレートに分解できるテンプレートを作成したいと考えています。たとえば、andに分解Array<5>されますが、非型テンプレート パラメーターの任意の型 (整数型、ポインター、メンバー ポインターなど) に対して一般的に機能します。template<int> Array5

テンプレートの特殊化を使用して、最初に試してください。

template<typename T> struct foo { enum { n = 1 }; };

template<int x> struct bar { enum { n = x }; };

template<typename T, template<T> class X, T x>
struct foo< X<x> > { enum { n = x }; }; // here x must be of integral type, but that's just for testing

int main(int, char**) { return foo< bar<16> >::n; }

Clang 3.1 は次のように述べています。

test145.cpp:6:8: warning: class template partial specialization contains a template parameter that can not be deduced; this partial specialization will never be used
struct foo< X<x> > { enum { n = x }; };
       ^~~~~~~~~~~
test145.cpp:5:19: note: non-deducible template parameter 'T'                     
template<typename T, template<T> class X, T x>
                  ^
1 warning generated.

関数テンプレートを使用した 2 回目の試行:

template<typename T, T x> 
struct box 
{ 
    static constexpr T value() { return x; }
};

template<typename T, template<T> class X, T x>
box<T, x> foo(X<x>);

template<int> struct asdf { };

int main(int, char**) { return decltype(foo(*(asdf<9>*)0))::value(); }

クランは次のように述べています。

test150.cpp:12:41: error: no matching function for call to 'foo'
int main(int, char**) { return decltype(foo(*(asdf<9>*)0))::value(); }
                                        ^~~
test150.cpp:8:11: note: candidate template ignored: couldn't infer template argument 'T'
box<T, x> foo(X<x>);
          ^
1 error generated.

GCC 4.7 も同様のことを言っています。

これは基本的な制限ですか?

おまけの質問: そうだとすれば、有限の量のコードで無限の可能性をすべて処理する方法はありますか? (たとえばポインタでは難しくなります。あなたが書けないように見えるのと同じ理由で、あなたもtemplate<T>書けないと思いますtemplate<T*>。)

なぜ私が尋ねているのか聞かないでください。

4

2 に答える 2

2

この他の質問は、基本的に同じことを求めていますが、テンプレートの非タイプパラメータではなく、テンプレートタイプのパラメータを求めています。テンプレートメタプログラミング:(特性?)指定されたテンプレートをタイプT <T2、T3 N、T4、...>に分析します。

タイプパラメータの場合、それは本当に簡単です。コードは次のようになります。

#include <tuple>
#include <vector>

template <class T> struct explode;

template <template <class... Args> class T, class... N>
struct explode<T<N...>>
{
    typedef T<N...> type;
    template <class... Args> using template_ = T<Args...>;
    template <int I> using type_parameter =
        typename std::tuple_element<I, std::tuple<N...>>::type;
};

#if TESTING
void test_harness()
{
    typedef explode<std::vector<int>> exv;

    exv::template_<char> vchar;  // The second parameter still has its default argument!
    exv::template_<exv::type_parameter<0>, exv::type_parameter<1>> vint;

    static_assert(std::is_same<exv::template_<char>, std::vector<char>>::value, "");
    static_assert(std::is_same<decltype(vchar), std::vector<char>>::value, "");
    static_assert(std::is_same<decltype(vint), std::vector<int>>::value, "");
    static_assert(std::is_same<exv::type, std::vector<int>>::value, "");
    static_assert(std::is_same<exv::type_parameter<0>, int>::value, "");
    static_assert(std::is_same<exv::type_parameter<1>, std::allocator<int>>::value, "");
}
#endif

しかし、型以外のパラメーターについては、それが可能かどうかはまだわかりません。似たようなコードから始めることができます

template <class... ArgTypes, template <ArgTypes... Args> class T, ArgTypes... N>
struct explode<T<N...>>
{
    typedef T<N...> type;
    template <ArgTypes... Args> using template_ = T<Args...>;
    template <int I> using type_of_parameter =
        typename std::tuple_element<I, std::tuple<ArgTypes...>>::type;
    template <int I> struct nontype_parameter {
        static constexpr type_of_parameter<I> value() {
            return std::get<I>(std::tuple<ArgTypes...>(N...));
        }
    };
};

};

しかし、Clangは(少なくとも)それを受け入れません:

test.cc:8:8: warning: class template partial specialization contains a template
      parameter that can not be deduced; this partial specialization will never
      be used
struct explode<T<N...>>
       ^~~~~~~~~~~~~~~~
test.cc:7:20: note: non-deducible template parameter 'ArgTypes'
template <class... ArgTypes, template <ArgTypes... Args> class T, ArgTypes... N>
                   ^

そして、その問題をなんとかして解消したとしても、標準ライブラリは何らかの理由でそうではないのでstd::get、手作業でコーディングされたバージョンに置き換える必要があります。constexprstd::getconstexpr

于 2012-08-26T20:16:33.813 に答える