免责声明。请不要将这样的代码放入实际的代码库中。如果你这样做了,这个实现绝不是“最佳的”,应该在使用前清理(如果你这样做,可能会添加一个答案)。
我发现这是一个有趣的挑战,并找到了以下解决方案:
// Try this live at https://compiler-explorer.com/z/cqebd81ss
#include <type_traits>
template <typename... Pack>
struct ClassList;
template<typename...>
struct Join {
};
template<typename... Pack1, typename... Pack2>
struct Join<ClassList<Pack1...>, ClassList<Pack2...>> {
using Type = ClassList<Pack1..., Pack2...>;
};
template<typename...>
struct RemoveSingleTypeFromList {
};
template<typename Target, typename... Pack>
struct RemoveSingleTypeFromList<Target, ClassList<Pack...>> {
using Type = ClassList<Pack...>;
};
template<typename Target, typename Parameter, typename... Pack>
struct RemoveSingleTypeFromList<Target, ClassList<Parameter, Pack...>> {
using Type = typename Join<
std::conditional_t<
std::is_same_v<Target, Parameter>,
ClassList<>,
ClassList<Parameter>
>,
typename RemoveSingleTypeFromList<Target, ClassList<Pack...>>::Type
>::Type;
};
template<typename... Pack>
struct RemoveTypesFromList {
};
template<typename... Types>
struct RemoveTypesFromList<ClassList<>, ClassList<Types...>> {
using Type = ClassList<Types...>;
};
template<typename Target, typename... RemainingTargets, typename... Types>
struct RemoveTypesFromList<ClassList<Target, RemainingTargets...>, ClassList<Types...>> {
using Type = typename RemoveSingleTypeFromList<
Target,
typename RemoveTypesFromList<
ClassList<RemainingTargets...>,
ClassList<Types...>
>::Type
>::Type;
};
// A few test cases to verify that it works
static_assert(std::is_same_v<
typename RemoveTypesFromList<
ClassList<int, float>,
ClassList<float, double, int, long>
>::Type,
ClassList<double, long>>);
static_assert(std::is_same_v<
typename RemoveTypesFromList<
ClassList<float>,
ClassList<float, double, float>
>::Type,
ClassList<double>>);
static_assert(std::is_same_v<
typename RemoveTypesFromList<
ClassList<int, int>,
ClassList<float, double, float>
>::Type,
ClassList<float, double, float>>);
如果您有兴趣确切了解其工作原理,请记住这是一个解决方案,而不是您可以从上到下编写的东西。在阅读这样的模板代码时,我发现逐步构建类似的实现最有用。