英文:
Expand template class list in C++
问题
我有一个用于处理类型 T 的模板函数
template<class T>
void EmplaceProcessor()
{
T* pProcessor = new T();
m_vItemProcessors.emplace_back(pProcessor);
}
如果我想要实现大量类型的插入到向量中,就像这样:
template<class... A>
void EmplaceAllProcessor()
{
const int size = sizeof...(A);
for (int i = 0; i < size; ++i)
{
EmplaceProcessor<A[i]>(); //如何展开它?
}
}
并且我想要调用 EmplaceAllProcessor<P1, P2, P3>();
来插入所有类型的处理器
我想要调用 EmplaceAllProcessor<P1, P2, P3>();
来插入所有类型的处理器,如何实现?
英文:
I have a template function to do sth with type T
template <class T>
void EmplaceProcessor()
{
T* pProcessor = new T();
m_vItemProcessors.emplace_back(pProcessor);
}
If I want to implement a lot of types to emplace to the vector, just sth like:
template<class...A>
void EmplaceAllProcessor()
{
const int size = sizeof...(A);
for (int i = 0; i < size; ++i)
{
EmplaceProcessor<A[i]>(); //how to expand it?????
}
}
and I want to call EmplaceAllProcessor<P1, P2, P3>(); to emplace all types of processor
I want to call EmplaceAllProcessor<P1, P2, P3>(); to emplace all types of processor, How can it be?
答案1
得分: 6
在C++11中,您可以使用一个虚拟数组初始化技巧:
template<class... A>
void EmplaceAllProcessor() {
int dummy[] = {0, (EmplaceProcessor<A>(), 0)...};
(void)dummy;
}
这里使用了逗号运算符表达式来依次调用A...
包中的每个类型的EmplaceProcessor<A>()
(按照初始化列表中的顺序进行评估,根据[dcl.init.list/4]的规定顺序)。第一个0
是为了支持空包,并且(void)dummy;
抑制了未使用变量的警告。
如果您想返回一个值,例如:bool EmplaceAllProcessor()
来返回是否成功以及bool EmplaceAllProcessor()
来告诉是否所有的EmplaceProcessor
都成功,可以进行如下扩展:
如果不需要短路操作,可以简单地扩展上述方法:
template<class... A>
bool EmplaceAllProcessor() {
bool res[] = {true, EmplaceProcessor<A>()...};
return std::all_of(std::begin(res), std::end(res), [](bool b) { return b; });
}
如果需要短路操作,可以使用另一小技巧:
template<class... A>
bool EmplaceAllProcessor() {
bool res = true;
bool dummy[] = {true, (res = res && EmplaceProcessor<A>())...};
(void)dummy;
return res;
}
英文:
In C++11, you can use a dummy array initialization trick:
template<class... A>
void EmplaceAllProcessor() {
int dummy[] = {0, (EmplaceProcessor<A>(), 0)...};
(void)dummy;
}
A comma operator expression is used to invoke EmplaceProcessor<A>()
for each type in the pack A...
, in order (the order of evaluation of arguments in a braced list is fixed by their order in that list per [dcl.init.list/4]). The first 0
is needed to support an empty pack and (void)dummy;
suppresses an unused variable warning.
> If I want to return a value, for example: bool EmplaceAllProcessor()
to return whether it is succeeded and bool EmplaceAllProcessor()
to tell if all the EmplaceProcessor
work succeeded, how can it be?
If you don't need short circuiting, it's a simple extension of the above approach:
template<class... A>
bool EmplaceAllProcessor() {
bool res[] = {true, EmplaceProcessor<A>()...};
return std::all_of(std::begin(res), std::end(res), [](bool b) { return b; });
}
If short circuiting is needed, another small trick might be used:
template<class... A>
bool EmplaceAllProcessor() {
bool res = true;
bool dummy[] = {true, (res = res && EmplaceProcessor<A>())...};
(void)dummy;
return res;
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论