模板参数包的参数为T.

时间:2013-10-02 11:43:36

标签: c++ c++11

我有一个组件地图。组件是具有一些数据的POD类型。每个组件都有唯一的标识符。地图在任何时候都只能拥有给定类型的一个组件。因此,我希望能够查询地图所拥有的组件。这是我用来完成此任务的代码:

template <typename T>
bool has()
{
    auto found = map.find(T::tag);
    if (found != map.end()) return true;
    else return false;
}

这会导致代码笨拙,如:something.has<Component<int>>() && something.has<Component<float>>() ... etc;

为了减少代码杂乱,我想使用可变参数模板。

template <typename T, typename... Args>
bool hasz()
{
    has<T>();
    has<Args>()...; /* expected ‘;’ before ‘...’ token */
}

不应该has<Args>()...扩展为(伪)has<Args[0]>(), has<Args[1]>(), etc...(这是合法的语法)?是否可以这样做?

2 个答案:

答案 0 :(得分:7)

是的,你只需要递归调用函数:

template <typename T>
bool has()
{
    return map.end() != map.find(T::tag);
}

template <typename T, typename... Args>
bool has()
{
    return has<T>() && has<Args...>();
}

它是如何工作的?

您有两个版本的功能:一个带有一个参数,另一个带有n个参数。第一个用作基本情况,后者用作递归情况 所以,如果你这样做:

has<bool,int,char,float>();

跟踪是:

  

致电has<bool,int,char,float>()(致递归案件)
  致电has<bool,int,char>()(呼吁递归案件)
  致电has<bool,int>()(呼吁递归案件)
  致电has<bool>()(调用基本案例)

注意:当然这个示例不起作用,因为我在示例中使用的类型没有::tag成员。它只是呼叫追踪的一个例子。 另外,我已经将跟踪简化为不会使示例过于复杂。真正的痕迹是:

  

致电has<bool,int,char,float>()(致递归案件)
  ....致电has<bool>()(调用基础案例)//左右&amp;&amp;
  ....致电has<int,char,float>()(呼吁递归案件)//&amp;&amp;
的右侧   ........拨打has<int>()(呼叫基本情况)//左侧&amp;&amp;
  ........拨打has<char,float>()(呼叫递归案例)//&amp;&amp;&amp;的右侧   ............拨打has<char>()(拨打基本案​​例)//&amp;&amp;
左侧   ............拨打has<float>()(呼叫基本情况)//右侧&amp;&amp;

答案 1 :(得分:2)

您可以使用std::min

#include<algorithm>

template <typename... Args>
bool hasz()
{
    return std::min({has<Args>()...});
}

请注意,这没有短路行为 - 它将始终为所有参数评估has<Args>。如果是问题,那就使用递归版本。