C++:模板类型的提取

C++: Extraction of template types

我正在开发编译时包装器库,偶然发现了从给定类型中提取模板参数类型的问题。

情况如下。我有一个不变的 class R:

template <class T>
class R {};

我还有一个不可更改的main函数:

int main()
{
    auto r = new R<int>();

    // Function that knows the type of 'r'
    create_obj<decltype(r)>();

    delete r;
    return 0;
}

create_obj 函数是我正在处理的函数。为了可视化,我会这样写:

template< class C >
void create_obj()
{
    // Print the type of the function (Output: R<int>*)
    std::cout << boost::typeindex::type_id<C>().pretty_name() << std::endl;
}

问题是我需要从 create_obj 函数访问 R class 的 int 模板参数类型。

伪代码:

template< 
    template < class T >
    class C<T>
>
void create_obj()
{
    // Print the type of the function (Output: int)
    std::cout << boost::typeindex::type_id<T>().pretty_name() << std::endl;
}

可以吗?我正在浏览 C++ 文档,但找不到任何方法从 class 定义中“分离”模板参数类型。

是的,这是可能的,一种方法:

template<typename T>
class R{};


template<typename C>
struct extract_impl{};

template<typename T>
struct extract_impl<R<T>>{
    using type = T;
};

template<typename C>
using extracted_type = typename extract_impl<std::remove_pointer_t<std::decay_t<C>>>::type;

template< class C >
void create_obj()
{
    static_assert(std::is_same_v<extracted_type<C>,int>);
}
int main()
{
    create_obj<R<int>>();
}

惯例是 R 本身会通过 using 公开类型,但您写道它是不可更改的。

我改为通过 r

的类型调用 create_obj()
create_obj<decltype(r)>();

直接传过来就可以调用r,解决方法很简单

template <typename T>
void create_obj (R<T> const *)
 { /* do something with T */ }

但是如果你想调用 create_obj() 只传递类型 R<T>(或指向 R<T> 的类型指针)而不实例化类型 R<T> 的对象,你可以定义一个轻量级类型包装器

template <typename>
struct typeWrapper
 { /* empty! */ };

重新定义 create_obj() 接收 typeWrapperR<T> 指针

template <typename T>
void create_obj (typeWrapper<R<T> *> const &)
 { /* do something with T */ }

并使用 decltype(r)

调用它
create_obj(typeWrapper<decltype(r)>{});

或直接R<int> *

create_obj(typeWrapper<R<int> *>{});

另一种选择是将 create_obj 声明为 struct/class

template <typename>
struct create_obj;

并且仅定义基于 R<T> * 指针的特化,其中包含 static func() 方法

template <typename T>
struct create_obj<R<T> *>
 {
   static void func ()
    { /* do something with T */ } 
 };

可以通过decltype(r)

使用
create_obj<decltype(r)>::func();

或通过R<int> *

create_obj<R<int> *>::func();

如果您愿意,可以在 create_obj() 中插入一个普通(非 static)方法,而不是 static func() 方法;也许 operator()。但是,这样,您必须实例化一个 create_obj 对象来调用该方法。