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()
接收 typeWrapper
的 R<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
对象来调用该方法。
我正在开发编译时包装器库,偶然发现了从给定类型中提取模板参数类型的问题。
情况如下。我有一个不变的 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()
接收 typeWrapper
的 R<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
对象来调用该方法。