แก้ไขเนื่องจากตัวแปรว่างเปล่า ( std::variant<>
) เกิดขึ้นไม่ดี (ตามcppreference ) และควรใช้std::variant<std::monostate>
แทนฉันได้แก้ไขคำตอบ (เพิ่มความtuple2variant()
เชี่ยวชาญสำหรับ tuple ว่าง) เพื่อรองรับกรณีเมื่อรายการประเภทสำหรับV1
หรือV2
ว่างเปล่า
มันเป็นdecltype()
อาการเพ้อเล็กน้อยแต่ ... หากคุณประกาศตัวกรองผู้ช่วยสองสามหน้าที่ดังต่อไปนี้
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 ();
และ tuple ฟังก์ชั่นที่แตกต่างกัน (ที่มีความเชี่ยวชาญสำหรับอันดับที่ว่างเปล่าเพื่อหลีกเลี่ยงที่ว่างเปล่าstd::variant
)
std::variant<std::monostate> tuple2variant (std::tuple<> const &);
template <typename ... Ts>
std::variant<Ts...> tuple2variant (std::tuple<Ts...> const &);
ชั้นเรียนของคุณ (?) กลายเป็น
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>()... ))>()));
};
หากคุณต้องการบางสิ่งที่ธรรมดากว่า (หากคุณต้องการส่งผ่านstd::arithmetic
เป็นพารามิเตอร์เทมเพลต) คุณสามารถแก้ไขfilterArithm()
ฟังก์ชั่นที่ส่งผ่านพารามิเตอร์ตัวกรองเทมเพลตแม่แบบF
(เปลี่ยนชื่อ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 ();
TheAnswer
ระดับกลายเป็น
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>()... ))>()));
};
และการTA
ประกาศใช้std::is_arithmetic
using TA = TheAnswer<std::variant<bool, char, std::string, int, float,
double, std::vector<int>>,
std::is_arithmetic>;
ต่อไปนี้เป็นตัวอย่างการรวบรวมแบบสมบูรณ์ด้วยstd::is_arithmetic
พารามิเตอร์ as และV2
กรณีว่างเปล่า
#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...
ด้านในstd::variant
โดยตรงเช่นนี้ ?