1

我有一张组件图。组件是具有一些数据的 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...(这将是合法的语法)?有可能做到这一点吗?

4

2 回答 2

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成员。它只是调用跟踪的一个例子。此外,我还简化了跟踪,以免示例过于复杂。真正的痕迹将是:

call to has<bool,int,char,float>()(Call to recursive case)
....call to has<bool>()(Call to base case) //左侧 &&
....call to has<int,char,float>()(Call to recursive case) //右侧 &&
.... ....call to has<int>()(Call to base case) //左侧 &&
........call to has<char,float>()(Call to recursive case) //右侧 &&
........ ....call to has<char>()(Call to base case) //&& 的左侧....call
to (Call to base case) //&&has<float>()的右侧

于 2013-10-02T11:51:35.137 回答
2

您可以使用std::min

#include<algorithm>

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

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

于 2013-10-02T11:55:03.567 回答