扩展C++中的模板类列表

huangapple go评论76阅读模式
英文:

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 &lt;class T&gt;
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&lt;class...A&gt; 
void EmplaceAllProcessor()
{
    const int size = sizeof...(A);
    for (int i = 0; i &lt; size; ++i)
    {
        EmplaceProcessor&lt;A[i]&gt;();     //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&lt;class... A&gt; 
void EmplaceAllProcessor() {
    int dummy[] = {0, (EmplaceProcessor&lt;A&gt;(), 0)...};
    (void)dummy;
}

A comma operator expression is used to invoke EmplaceProcessor&lt;A&gt;() 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&lt;class... A&gt; 
bool EmplaceAllProcessor() {
    bool res[] = {true, EmplaceProcessor&lt;A&gt;()...};
    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&lt;class... A&gt; 
bool EmplaceAllProcessor() {
    bool res = true;
    bool dummy[] = {true, (res = res &amp;&amp; EmplaceProcessor&lt;A&gt;())...};
    (void)dummy;
    return res;
}

huangapple
  • 本文由 发表于 2023年1月9日 10:59:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/75052803.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定