दिए गए std को विभाजित करें :: दिए गए मानदंडों द्वारा प्रकार प्रकार


20

किसी दिए गए प्रकार से कैसे

using V = std::variant<bool, char, std::string, int, float, double, std::vector<int>>;

दो प्रकारों की घोषणा करें

using V1 = std::variant<bool, char, int, float, double>;
using V2 = std::variant<std::string, std::vector<int>>;

कहाँ से V1सभी अंकगणितीय प्रकार शामिल हैं Vऔर V2सभी गैर अंकगणितीय प्रकार शामिल हैं V?

V उदाहरण के लिए, टेम्प्लेट क्लास का एक पैरामीटर हो सकता है:

template <class V>
struct TheAnswer
{
    using V1 = ?;
    using V2 = ?;
};

सामान्य तौर पर मानदंड constexprइस तरह एक चर हो सकता है :

template <class T>
constexpr bool filter;

जवाबों:


6

यदि किसी भी कारण से आप बैरी के संक्षिप्त और उचित उत्तर का उपयोग नहीं करना चाहते हैं, तो यहां एक है जो न तो है (धन्यवाद @ xskxzr को हटाने के लिए अजीब "बूटस्ट्रैप" विशेषज्ञता है, और खाली अधिकतम कोने के मामले में मुझे चेतावनी देने के लिए @ max66 के लिए) :

namespace detail {
    template <class V>
    struct convert_empty_variant {
        using type = V;
    };

    template <>
    struct convert_empty_variant<std::variant<>> {
        using type = std::variant<std::monostate>;
    };

    template <class V>
    using convert_empty_variant_t = typename convert_empty_variant<V>::type;

    template <class V1, class V2, template <class> class Predicate, class V>
    struct split_variant;

    template <class V1, class V2, template <class> class Predicate>
    struct split_variant<V1, V2, Predicate, std::variant<>> {
        using matching = convert_empty_variant_t<V1>;
        using non_matching = convert_empty_variant_t<V2>;
    };

    template <class... V1s, class... V2s, template <class> class Predicate, class Head, class... Tail>
    struct split_variant<std::variant<V1s...>, std::variant<V2s...>, Predicate, std::variant<Head, Tail...>>
    : std::conditional_t<
        Predicate<Head>::value,
        split_variant<std::variant<V1s..., Head>, std::variant<V2s...>, Predicate, std::variant<Tail...>>,
        split_variant<std::variant<V1s...>, std::variant<V2s..., Head>, Predicate, std::variant<Tail...>>
    > { };
}

template <class V, template <class> class Predicate>
using split_variant = detail::split_variant<std::variant<>, std::variant<>, Predicate, V>;

इसे वैंडबॉक्स पर लाइव देखें


शायद आप इस तरह सीधे Types...अंदर खोल सकते हैं ? std::variant
xskxzr

क्षमा करें, लेकिन ... जहाँ तक मुझे पता है, एक खाली std::variantबीमार है।
अधिकतम

@ max66 जाहिर है केवल instantiating std::variant<> बीमार बनाई है, तो मैं स्पष्ट में हूँ। मैं इसे ट्विक कर दूंगा V1और V2फिर से std::variant<std::monostate>गिरूंगा।
क्वेंटिन

आह ... यदि केवल तत्काल किया गया तो बीमार बने ... ठीक है; मुझे उचित लगता है।
अधिकतम ६६

14

Boost.Mp11 के साथ , यह एक छोटा लाइनर है (हमेशा की तरह):

using V1 = mp_filter<std::is_arithmetic, V>;
using V2 = mp_remove_if<V, std::is_arithmetic>;

आप भी उपयोग कर सकते हैं:

using V1 = mp_copy_if<V, std::is_arithmetic>;

दो अधिक सममित बनाने के लिए।


वैकल्पिक रूप से,

using P = mp_partition<V, std::is_arithmetic>;
using V1 = mp_first<P>;
using V2 = mp_second<P>;

यह किन विचारों mp_filterपर आधारित है?
एलेक्सी स्टारिंस्की 14

@AlexeyStarinsky मैं इस सवाल को नहीं समझता - आपका क्या मतलब है, क्या विचार हैं?
बैरी

3
@AlexeyStarinsky डॉक्यूमेंटेशन पढ़ें, यह कुछ पोस्ट के लिंक भी है जो पीटर ने लिखा था, यह काफी जानकारीपूर्ण है।
बैरी 15

4
@MaximEgorushkin यह सबसे अच्छा मेटाप्रोग्रामिंग लाइब्रेरी imo है। मेरे पास यहाँ बहुत सारे उत्तर हैं जो "Boost.Mp11 के साथ शुरू होते हैं, यह एक छोटा लाइनर है"
बैरी

1
@ बैरी मैं अभी डॉक्स पढ़ रहा हूं और यह बूस्ट से बेहतर लग रहा है। एमपीएल।
मैक्सिम Egorushkin

2

EDIT यह देखते हुए कि एक खाली संस्करण ( std::variant<>) बीमार है ( cppreference के अनुसार ) और इसका उपयोग किया जाना चाहिए std::variant<std::monostate>, मैंने tuple2variant()इस मामले का समर्थन करने के लिए उत्तर ( खाली ट्यूपल के लिए एक विशेषज्ञता जोड़ा ) को संशोधित किया है जब प्रकार की सूची के लिए 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 ();

और वैरिएंट फ़ंक्शन के लिए एक ट्यूपल (खाली ट्यूपल्स के लिए विशेषज्ञता के साथ, खाली से बचने के लिए 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पैरामीटर और एक 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> );
 }

आपका समाधान काम नहीं करता है void
xskxzr

@xskxzr - क्षमा करें, लेकिन मुझे आपकी आपत्ति समझ में नहीं आती। void, जहाँ तक मुझे पता है, टाइप ए में निषिद्ध है std::variant
1966 को अधिकतम

1
मेरा बुरा, मुझे महसूस नहीं हुआ कि std::variant<void>वह बीमार है, लेकिन ऐसा लगता std::variant<>है कि अगर इसकी परिभाषा त्वरित नहीं है तो ठीक है
xskxzr
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.