T 是 C++ 中模板的实例

Is T an instance of a template in C++?

本文关键字:实例 C++      更新时间:2023-10-16

>假设我在模板中,我想知道类型参数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

当简单的重载就足够时,为什么要使用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>>
{ };

部分规范应该能够做到这一点。

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)交互。

处理 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)
{
  // ...
}