EDIT Cho rằng một biến thể trống ( std::variant<>
) không được hình thành (theo cppreference ) và nên được sử dụng std::variant<std::monostate>
thay thế, tôi đã sửa đổi câu trả lời (thêm một tuple2variant()
chuyên ngành cho tuple trống) để hỗ trợ trường hợp khi danh sách các loại cho V1
hoặc V2
trống.
Đó là một chút decltype()
mê sảng nhưng ... nếu bạn khai báo một vài bộ lọc trợ giúp như sau
template <bool B, typename T>
constexpr std::enable_if_t<B == std::is_arithmetic_v<T>, std::tuple<T>>
filterArithm ();
template <bool B, typename T>
constexpr std::enable_if_t<B != std::is_arithmetic_v<T>, std::tuple<>>
filterArithm ();
và một tuple cho chức năng biến thể (với một chuyên môn cho các bộ dữ liệu trống, để tránh một bộ trống std::variant
)
std::variant<std::monostate> tuple2variant (std::tuple<> const &);
template <typename ... Ts>
std::variant<Ts...> tuple2variant (std::tuple<Ts...> const &);
lớp học của bạn đơn giản (?) trở thành
template <typename ... Ts>
struct TheAnswer<std::variant<Ts...>>
{
using V1 = decltype(tuple2variant(std::declval<
decltype(std::tuple_cat( filterArithm<true, Ts>()... ))>()));
using V2 = decltype(tuple2variant(std::declval<
decltype(std::tuple_cat( filterArithm<false, Ts>()... ))>()));
};
Nếu bạn muốn một cái gì đó chung chung hơn (nếu bạn muốn truyền std::arithmetic
dưới dạng tham số mẫu), bạn có thể sửa đổi filterArithm()
hàm truyền tham số bộ lọc mẫu-mẫu F
(được đổi tên filterType()
)
template <template <typename> class F, bool B, typename T>
constexpr std::enable_if_t<B == F<T>::value, std::tuple<T>>
filterType ();
template <template <typename> class F, bool B, typename T>
constexpr std::enable_if_t<B != F<T>::value, std::tuple<>>
filterType ();
Các TheAnswer
lớp học trở thành
template <typename, template <typename> class>
struct TheAnswer;
template <typename ... Ts, template <typename> class F>
struct TheAnswer<std::variant<Ts...>, F>
{
using V1 = decltype(tuple2variant(std::declval<decltype(
std::tuple_cat( filterType<F, true, Ts>()... ))>()));
using V2 = decltype(tuple2variant(std::declval<decltype(
std::tuple_cat( filterType<F, false, Ts>()... ))>()));
};
và TA
tuyên bố cũng mấtstd::is_arithmetic
using TA = TheAnswer<std::variant<bool, char, std::string, int, float,
double, std::vector<int>>,
std::is_arithmetic>;
Sau đây là một ví dụ biên dịch đầy đủ với std::is_arithmetic
tham số và V2
trường hợp trống
#include <tuple>
#include <string>
#include <vector>
#include <variant>
#include <type_traits>
std::variant<std::monostate> tuple2variant (std::tuple<> const &);
template <typename ... Ts>
std::variant<Ts...> tuple2variant (std::tuple<Ts...> const &);
template <template <typename> class F, bool B, typename T>
constexpr std::enable_if_t<B == F<T>::value, std::tuple<T>>
filterType ();
template <template <typename> class F, bool B, typename T>
constexpr std::enable_if_t<B != F<T>::value, std::tuple<>>
filterType ();
template <typename, template <typename> class>
struct TheAnswer;
template <typename ... Ts, template <typename> class F>
struct TheAnswer<std::variant<Ts...>, F>
{
using V1 = decltype(tuple2variant(std::declval<decltype(
std::tuple_cat( filterType<F, true, Ts>()... ))>()));
using V2 = decltype(tuple2variant(std::declval<decltype(
std::tuple_cat( filterType<F, false, Ts>()... ))>()));
};
int main ()
{
using TA = TheAnswer<std::variant<bool, char, std::string, int, float,
double, std::vector<int>>,
std::is_arithmetic>;
using TB = TheAnswer<std::variant<bool, char, int, float, double>,
std::is_arithmetic>;
using VA1 = std::variant<bool, char, int, float, double>;
using VA2 = std::variant<std::string, std::vector<int>>;
using VB1 = VA1;
using VB2 = std::variant<std::monostate>;
static_assert( std::is_same_v<VA1, TA::V1> );
static_assert( std::is_same_v<VA2, TA::V2> );
static_assert( std::is_same_v<VB1, TB::V1> );
static_assert( std::is_same_v<VB2, TB::V2> );
}
Types...
bên trongstd::variant
trực tiếp, như thế này ?