变量模板扩展期间类型的C++索引
C++ index of type during variadic template expansion
我有一个简单但令人生畏的问题,我自己无法解决。我有类似的东西
template<class T, class... Args>
T* create(SomeCastableType* args, size_t numArgs)
{
return new T(static_cast<Args>(args[INDEX_OF_EXPANSION])...);
}
假设SomeCastableType
可转换为任何类型。显然,我不能得到的是INDEX_OF_EXPANSION
。
非常感谢你的帮助。
指数技巧,yay~
template<class T, class... Args, std::size_t... Is>
T* create(U* p, indices<Is...>){
return new T(static_cast<Args>(p[Is])...);
}
template<class T, class... Args>
T* create(U* p, std::size_t num_args){
assert(num_args == sizeof...(Args));
return create<T, Args...>(p, build_indices<sizeof...(Args)>{});
}
当然,我强烈建议使用智能指针和std::vector
,而不是原始指针。
假设
SomeCastableType
可转换为任何类型。显然,我不能得到的是INDEX_OF_EXPANSION
。
由于C++14,您可以使用std::make_index_sequence
助手在标准库的支持下执行@Xeo提到的索引技巧,如下所示:
template<class T, class... Args, std::size_t... Is>
T* create(SomeCastableType* p, std::index_sequence<Is...>)
{
return new T(static_cast<Args>(p[Is])...);
}
template<class T, class... Args>
T* create(SomeCastableType* p, std::size_t num_args)
{
return create<T, Args...>(p, std::make_index_sequence<sizeof...(Args)>());
}
使用c++17的constexpr-if,我们可以获得一个更可读/更易懂的索引查找函数实现(我从未想过这里的其他答案):
template<typename Target, typename ListHead, typename... ListTails>
constexpr size_t getTypeIndexInTemplateList()
{
if constexpr (std::is_same<Target, ListHead>::value)
return 0;
else
return 1 + getTypeIndexInTemplateList<Target, ListTails...>();
}
这可以如下使用:
size_t index = getTypeIndexInTemplateList<X, Foo,Bar,X,Baz>(); // this will return 2
或者,如果你有一个不同的模板类型,并想在其中获得一个索引:
template<typename... Types>
class Container
{
public:
size_t getIndexOfType<typename T>() { return getTypeIndexInTemplateList<T, Types...>(); }
};
...
Container<Foo, Bar, X, Baz> container;
size_t container.getIndexOfType<X>(); // will return 2
它的工作方式是递归地从列表中删除类型。所以第一个例子的调用顺序基本上是:
getTypeIndexInTemplateList<X, Foo, Bar,X,Baz>() // ListHead = Foo, ListTails = Bar,X,Baz
getTypeIndexInTemplateList<X, Bar, X,Baz>() // ListHead = Bar, ListTails = X, Baz
getTypeIndexInTemplateList<X, X, Baz>() // ListHead = X, so now we return. Recursive addition takes care of calculating the correct index
函数是constexpr,所以这一切都将在编译时执行,在运行时它只是一个常量。
如果您要求一个列表中不存在的类型,它将生成编译错误,因为它将尝试用太少的模板参数调用函数。当然,如果该类型存在多次,这将只返回列表中该类型的第一个实例的索引。
您需要一个助手:
#include <tuple>
template <typename T, bool, typename Tuple, unsigned int ...I>
struct helper
{
static T * go(S * args)
{
return helper<T, sizeof...(I) + 1 == std::tuple_size<Tuple>::value,
Tuple, I..., sizeof...(I)>::go(args);
}
};
template <typename T, typename ...Args, unsigned int ...I>
struct helper<T, true, std::tuple<Args...>, I...>
{
static T * go(S * args)
{
return new T(static_cast<Args>(args[I])...);
}
};
template <typename T, typename ...Args>
T * create(S * args)
{
return helper<T, sizeof...(Args) == 0, std::tuple<Args...>>::go(args);
}
编辑:经过测试,似乎有效。
相关文章:
- 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作为变体中的替代类型之一
- 类中的字符串不命名类型