Reputation: 5405
I have a struct Robot
:
template<typename... FeatureList>
struct Robot {
Robot() = default;
};
That it can be configured with a few features (a few structs are used as token here):
struct CanWalk {
};
struct CanNotWalk {
};
struct CanFly {
};
struct CanNotFly {
};
Robot<CanWalk, CanFly> robot_A = Robot<CanWalk, CanFly>();
Then I have no idea how to implement a bool function isConfiguredWith()
within struct Robot
that tells me if a feature is encoded into the struct:
template<typename... FeatureList>
template<typename Feature>
constexpr bool Robot<FeatureList...>::isConfiguredWith() {
// how do I implement it?
return false;
}
int main() {
Robot<CanWalk, CanFly> robot_A = Robot<CanWalk, CanFly>();
static_assert(robot_A.isConfiguredWith<CanWalk>());
static_assert(robot_A.isConfiguredWith<CanFly>());
return 0;
}
How do I loop through FeatureList
to find out if Feature
exist in the lists, in compilation time?
Full code:
struct CanWalk {
};
struct CanNotWalk {
};
struct CanFly {
};
struct CanNotFly {
};
template<typename... FeatureList>
struct Robot {
Robot() = default;
template<typename Feature>
constexpr bool isConfiguredWith();
};
template<typename... FeatureList>
template<typename Feature>
constexpr bool Robot<FeatureList...>::isConfiguredWith() {
return false;
}
int main() {
Robot<CanWalk, CanFly> robot_A = Robot<CanWalk, CanFly>();
static_assert(robot_A.isConfiguredWith<CanWalk>());
static_assert(robot_A.isConfiguredWith<CanFly>());
return 0;
}
Upvotes: 2
Views: 76
Reputation: 117268
You could add a feature test type trait:
#include <type_traits>
template<class Feature, class... FeatureList>
struct has_feature {
static constexpr bool value = (std::is_same_v<Feature, FeatureList> || ...);
};
template<class Feature, class... FeatureList>
inline constexpr bool has_feature_v = has_feature<Feature,FeatureList...>::value;
And use it in your Robot
class like this:
template<class... FeatureList>
struct Robot {
Robot() = default;
template<class Feature>
static constexpr bool isConfiguredWith() {
return has_feature_v<Feature,FeatureList...>;
}
};
(std::is_same_v<Feature, FeatureList> || ...)
is a fold expression.
Say FeatureList...
is CanWalk, CanFly
. The above fold expression then "unfolds" to:
std::is_same_v<Feature, CanWalk> || std::is_same_v<Feature, CanFly>
You can also investigate these template instantiations in more detail at cppinsights.io
Upvotes: 1
Reputation: 122133
You can write a trait like this:
#include <type_traits>
#include <iostream>
template<typename... FeatureList>
struct Robot {
Robot() = default;
};
struct CanWalk {};
struct CanNotWalk {};
struct CanFly {};
struct CanNotFly {};
template <typename Feature,typename... Features>
using has_feature_impl = std::integral_constant<bool,(std::is_same_v<Feature,Features> || ...)>;
template <typename Feature,typename T> struct has_feature;
template <typename Feature,typename... Features> struct has_feature<Feature,Robot<Features...>> : has_feature_impl<Feature,Features...> {};
int main()
{
using R1 = Robot<CanWalk,CanFly>;
std::cout << has_feature<CanWalk,R1>::value;
std::cout << has_feature<CanNotFly,R1>::value;
}
10
Upvotes: 1