Reputation: 38
I have a map of components. Components are POD types that have some data. Each component has a unique identifier. The map can own only one component of a given type at any time. As such, I want to be able to query the map's owned components. This is the code I'm using to accomplish this:
template <typename T>
bool has()
{
auto found = map.find(T::tag);
if (found != map.end()) return true;
else return false;
}
This would result in awkward code like: something.has<Component<int>>() && something.has<Component<float>>() ... etc;
In order to make the code less messy, I want to make use of variadic templates.
template <typename T, typename... Args>
bool hasz()
{
has<T>();
has<Args>()...; /* expected ‘;’ before ‘...’ token */
}
Shouldn't has<Args>()...
expand to (pseudo) has<Args[0]>(), has<Args[1]>(), etc...
(which would be legal syntax)? And is it possible to do this at all?
Upvotes: 1
Views: 151
Reputation: 14174
Yes, you only have to call the function recursivelly:
template <typename T>
bool has()
{
return map.end() != map.find(T::tag);
}
template <typename T, typename... Args>
bool has()
{
return has<T>() && has<Args...>();
}
You have two versions of the function: One with one parameter, and one with n parameters. The first is used as the base case, and the later is used as the recursive case.
So if you do this:
has<bool,int,char,float>();
The trace is:
call to
has<bool,int,char,float>()
(Call to recursive case)
call tohas<bool,int,char>()
(Call to recursive case)
call tohas<bool,int>()
(Call to recursive case)
call tohas<bool>()
(Call to base case)
NOTE: Of course this example does not work really, because the types I used in the example don't have a ::tag
member. Its only an example of the call trace indeed.
In addition, I have simplified the trace to not overcomplicate the example. The true trace will be:
call to
has<bool,int,char,float>()
(Call to recursive case)
....call tohas<bool>()
(Call to base case) //left side of the &&
....call tohas<int,char,float>()
(Call to recursive case) //right side of the &&
........call tohas<int>()
(Call to base case) //left side of the &&
........call tohas<char,float>()
(Call to recursive case) //right side of the &&
............call tohas<char>()
(Call to base case) //left side of the &&
............call tohas<float>()
(Call to base case) //right side of the &&
Upvotes: 7
Reputation: 15278
You can use std::min
:
#include<algorithm>
template <typename... Args>
bool hasz()
{
return std::min({has<Args>()...});
}
Note that this doesn't have short-circuit behavior - it will always evaluate has<Args>
for all arguments. If it's the problem, then use recursive version.
Upvotes: 2