I am designing a pipeline class that needs to extract a std::variant
from a list of distinct types in a filter class. For example:
template <typename T>
struct Filter {
using type = T;
// ...
}
template <typename... Filters>
struct Pipeline {
// how to properly define the variant type?
// std::variant<Filters::type...> buffer;
};
For example, if I have three different filter types:
Filter<int>, Filter<double>, Filter<std::string>
then, the variant should be std::variant<int, double, std::string>
. However, I need to remove duplicate types in the variant, for example:
Filter<int>, Filter<double>, Filter<std::string>, Filter<int>
then, the variant should NOT be std::variant<int, double, std::string, int>
but std::variant<int, double, std::string>
. Additionally, I need to replace void
with std::monostate
. For example:
Filter<int>, Filter<double>, Filter<void>, Filter<int>, Filter<void>
then, the variant should be std::variant<int, double, std::monostate>
.
How to design such a metaclass that can properly define the variant type based on the given type names template <typename... Filters>
using c 17?
CodePudding user response:
Based on Piotr's answer:
#include <variant>
template <typename T, typename... Ts>
struct unique { using type = T; };
template <typename... Ts, typename U, typename... Us>
struct unique<std::variant<Ts...>, U, Us...>
: std::conditional_t<(std::is_same_v<U, Ts> || ...),
unique<std::variant<Ts...>, Us...>,
unique<std::variant<Ts..., U>, Us...>> {};
template <typename... Ts>
using variant_t = typename unique<
std::variant<>,
std::conditional_t<std::is_same_v<Ts, void>, std::monostate, Ts>...>::type;
then your Pipeline
can be defined as:
template <typename T>
struct Filter {
using type = T;
};
template <typename... Filters>
struct Pipeline {
variant_t<typename Filters::type...> buffer;
};