显式指定模板模板类型
Explicitly specify template template types
本文关键字:类型 更新时间:2024-09-27
我正在学习模板。如果我混淆了概念模板/模板类型/模板参数,请纠正我。
我正试图编写一个模板函数来创建一个对象并返回它。对象的类型来自必须显式指定的模板参数。
result = createObject<ObjectType>();
不过,这个对象应该是一个模板。例如,一个容器。函数应该知道对象的类型及其模板参数。例如:
result = createObject<Container<ElementType>>();
我试着用模板模板参数来解决它:
template <template<class> class ContainerType, class ElementType>
auto createObject()
{
ContainerType<ElementType> result;
//do stuff...
return result;
}
//...
template<typename T>
struct Vector{};
//...
//const auto random_vec = createObject<Vector<float>>(); // ERROR.
const auto random_vec = createObject<Vector, float>();
第二种情况有效,第一种情况无效。上面写着candidate template ignored: invalid explicitly-specified argument for template parameter 'ContainerType'
。
有可能让它像第一种情况一样工作吗?给它一个类似Vector<float>
的东西,它可以推导出ContainerType
到Vector
和ElementType
到float
?是否可以重载或专门化此函数,使其以不同的方式处理某些类型的容器?我应该使用概念吗?
像这样进行分解的常用方法是通过部分专业化,这需要一个辅助类模板:
namespace detail {
template<class> struct create; // undefined
template<template<class T> class C,class T>
struct create<C<T>> {
static C<T> make() {/* … */}
};
}
template<class T>
T createObject() {return detail::create<T>::make();}
如果您想支持一般情况,可以定义主模板,也可以为其他类型的模板(如std::array
(添加其他专业化。
您可以创建一个类型特征来检查该类型是否是从模板实例化的:
#include <type_traits>
// trait to check if the type is instantiated from a template
template<typename T>
struct is_template_instance_type : std::false_type {};
template<template<class,class...> class C, class T, class... Rest>
struct is_template_instance_type<C<T,Rest...>> : std::true_type {
using class_type = C<T,Rest...>;
using value_type = T;
// using rest_types = std::tuple<Rest...>;
};
// Helper variable template - if needed for something later
template<class T>
inline constexpr bool is_template_instance_type_v = is_template_instance_type<T>::value;
然后你可以添加过载:
template<class T, class C = is_template_instance_type<T>, class U = typename C::class_type>
auto createObject() {
U result;
// typename C::value_type x; // if you need the value type
return result;
}
template<template<class,class...> class C, class T, class... Rest>
auto createObject() {
return createObject< C<T,Rest...> >();
}
然后它将与Vector<float>
、Vector, float
一起工作,但不与float
一起工作。
演示
您可以简单地执行以下操作:
template<typename T, typename V = typename T::value_type>
T createObject()
{
T t {}; // T will be e.g std::vector<int>
V v {}; // V will be int
// do work...
t.push_back(v++);
t.push_back(v++);
// ...work done
return t;
}
你可以这样使用它:
int main ()
{
auto obj1 = createObject<std::vector<int>>();
auto obj2 = createObject<std::list<double>>();
return 0;
}
相关文章:
- ArduinoJson 6.15.2:JsonObject没有命名类型
- 防止主数据类型C++的隐式转换
- 大量序列中核苷酸类型的快速计数
- 如何从C++中的依赖类型中获得它所依赖的类型
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- 是否可以初始化不可复制类型的成员变量(或基类)
- 如何获取std::result_of函数的返回类型
- 从父命名空间重载类型
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 我想将一个对T类型的非常量左值引用绑定到一个T类型的临时值
- Openssl 1.1.1d无效使用不完整的类型"struct dsa_st"
- 访问者访问变体并返回不同类型时出错
- 在VS2010-VS2015下编译时,如何使用decltype作为较大类型表达式的LHS
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- C++ 雷神库 - 使用资源加载器类时出现问题(不命名类型)
- 模板元程序查找相似的连续类型名称
- 是否可以从int转换为enum类类型
- 构造函数正在调用一个使用当前类类型的函数
- 我应该使用什么来代替void作为变体中的替代类型之一
- 类中的字符串不命名类型