C++模板参数:在编译时查找参数是否存在于参数列表中

C++ template parameter: to find out if a parameter exists in parameter list during compilation time

我有一个结构 Robot:

template<typename... FeatureList>
struct Robot {
    Robot() = default;
};

它可以配置一些功能(这里使用一些结构作为令牌):

struct CanWalk {
};
struct CanNotWalk {
};
struct CanFly {
};
struct CanNotFly {
};


Robot<CanWalk, CanFly> robot_A = Robot<CanWalk, CanFly>();

然后我不知道如何在结构 Robot 中实现 bool 函数 isConfiguredWith() 来告诉我功能是否被编码到结构中:


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;
}

如何遍历 FeatureList 以找出 Feature 是否存在于列表中,在编译时间

完整代码:

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;
}

你可以这样写一个特征:

#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;
}

Output:

10

您可以添加功能测试类型特征:

#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;

然后像这样在 Robot class 中使用它:

template<class... FeatureList>
struct Robot {
    Robot() = default;

    template<class Feature>
    static constexpr bool isConfiguredWith() {
        return has_feature_v<Feature,FeatureList...>;
    }
};

Demo

(std::is_same_v<Feature, FeatureList> || ...)fold expression.

假设 FeatureList...CanWalk, CanFly。上面的折叠表达式然后“展开”为:

std::is_same_v<Feature, CanWalk> || std::is_same_v<Feature, CanFly>

您还可以在 cppinsights.io

中更详细地研究这些模板实例化