13

テンプレートを使用していて、タイプパラメータTが特定のテンプレートのインスタンス化であるかどうかを知りたいとします。例std::shared_ptr

template<typename T>
void f(T&& param)
{
    if (instantiation_of(T, std::shared_ptr)) ...   // if T is an instantiation of 
                                                    // std::shared_ptr...
  ...
}

std :: enable_ifテストの一部としてこの種のテストを実行したいと思う可能性が高いです:

template<typename T>
std::enable_if<instantiation_of<T, std::shared_ptr>::type
f(T&& param) 
{
    ...
}

// other overloads of f for when T is not an instantiation of std::shared_ptr

これを行う方法はありますか?このソリューションは、標準ライブラリや変更できない他のライブラリを含む、考えられるすべてのタイプとテンプレートで機能する必要があることに注意してください。上記の使用はstd::shared_ptr、私がやりたいことのほんの一例です。

これが可能であれば、自分でテストを作成する方法、つまり実装する方法を教えてinstantiation_ofください。

4

3 に答える 3

11

enable_if単純なオーバーロードで十分な場合に使用するのはなぜですか?

template<typename T>
void f(std::shared_ptr<T> param) 
{
    // ...
}

あなたが本当にそのような特性を必要とするならば、私はこれがあなたを始めるべきだと思います(VC ++ 2010で大まかにテストされただけです):

#include <type_traits>

template<typename>
struct template_arg;

template<template<typename> class T, typename U>
struct template_arg<T<U>>
{
    typedef U type;
};

template<typename T>
struct is_template
{
    static T* make();

    template<typename U>
    static std::true_type check(U*, typename template_arg<U>::type* = nullptr);
    static std::false_type check(...);

    static bool const value =
        std::is_same<std::true_type, decltype(check(make()))>::value;
};

template<
    typename T,
    template<typename> class,
    bool Enable = is_template<T>::value
>
struct specialization_of : std::false_type
{ };

template<typename T, template<typename> class U>
struct specialization_of<T, U, true> :
    std::is_same<T, U<typename template_arg<T>::type>>
{ };
于 2012-05-30T17:40:42.270 に答える
9

部分的な仕様でそれができるはずです。

template <template <typename...> class X, typename T>
struct instantiation_of : std::false_type {};

template <template <typename...> class X, typename... Y>
struct instantiation_of<X, X<Y...>> : std::true_type {};

http://ideone.com/4n346

私は実際にテンプレートテンプレート構文を調べなければなりませんでした。なぜなら、基本的にこれまで使用する理由がなかったからです。

std::vector追加のデフォルトの引数のように、これがテンプレートとどのように相互作用するかわからない。

于 2012-05-30T17:46:07.297 に答える
3

T &&を処理するときにこれを行う最善の方法は、チェックを行う前に必ずremove_referenceを実行することです。これは、基になる型Tが参照型または値型である可能性があり、テンプレートの部分特殊化が正確に機能する必要があるためです。それを行うためのコードの上の答えと組み合わせると、次のようになります。

template <
  typename T,
  template <typename...> class Templated
> struct has_template_type_impl : std::false_type {};

template <
  template <typename...> class T,
  typename... Ts
> struct has_template_type_impl<T<Ts...>, T> : std::true_type {};

template <
  typename T, 
  template <typename...> class Templated
> using has_template_type = has_template_type_impl<
    typename std::remove_reference<T>::type,
    Templated
>;

そして、あなたは勝利への道をenable_ifするだけです:

template <typename T>
typename std::enable_if<has_template_type<T, std::shared_ptr>::value>::type
f(T&& param)
{
  // ...
}
于 2012-05-30T18:35:40.620 に答える