প্রদত্ত মানদণ্ড দ্বারা প্রদত্ত 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 , এবং খালি ভেরিয়েন্ট কর্নারের ক্ষেত্রে আমাকে সতর্ক করার জন্য @ ম্যাক্স66 ) :

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মত সরাসরি এই ?
এক্সস্কক্সজার

দুঃখিত, তবে ... যতদূর আমি জানি, একটি খালিটি std::variantগঠনযুক্ত।
সর্বাধিক 66

@ সর্বোচ্চ 66 দৃশ্যত কেবল তাত্ক্ষণিক কাজটিই দুর্গঠিত std::variant<>, সুতরাং আমি পরিষ্কার in আমি এটা যাতে খামচি হবে V1এবং V2ফিরে আসবে std::variant<std::monostate>যদিও।
কোয়ান্টিন

আহ ... তাত্ক্ষণিক হলেই খারাপ-গঠন ... ঠিক আছে; আমার কাছে যুক্তিযুক্ত মনে হচ্ছে
সর্বোচ্চ 66

14

বুস্ট.এমপি 11 এর সাথে এটি একটি সংক্ষিপ্ত ওয়ান-লাইনার (সর্বদা হিসাবে):

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ভিত্তিতে?
অ্যালেক্সি স্টারিনস্কি

@ অ্যালেক্সিস্টারিনস্কি আমি প্রশ্নটি বুঝতে পারি না - আপনার অর্থ কী, কোন ধারণা?
ব্যারি

3
@ অ্যালেক্সিস্টারিনস্কি ডকুমেন্টেশনটি পড়ুন, এটি পিটারের কিছু পোস্টের সাথে লিঙ্ক করেছে, এটি বেশ তথ্যপূর্ণ।
ব্যারি

4
@ ম্যাক্সিম এগারোশকিন এটি সেরা রূপক গ্রন্থাগার ইমো। আমার এখানে প্রচুর উত্তর রয়েছে যা "বুস্ট.এমপি 11 দিয়ে শুরু করুন, এটি একটি স্বল্প ওয়ান লাইনার"
ব্যারি

1
@ ব্যারি আমি এখনই ডক্সটি পড়ছি এবং এটি boost.MPL এর চেয়ে অনেক ভাল দেখাচ্ছে।
ম্যাক্সিম এগারুশকিন

2

সম্পাদনা প্রদত্ত যে একটি খালি বৈকল্পিক ( 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 ();

এবং ভেরিয়েন্ট ফাংশন (একটি ফাঁকা এড়ানোর জন্য খালি tuples জন্য একটি বিশেষীকরণ সহ 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
এক্সস্কক্সজার

@ এক্সস্কক্সজার - দুঃখিত তবে আমি আপনার আপত্তি বুঝতে পারি না। voidযতদূর আমি জানি, a তে টাইপ করা নিষিদ্ধ std::variant
সর্বোচ্চ 66

1
আমার খারাপ, আমি বুঝতে পারি নি যে std::variant<void>এটি দুর্গঠিত, তবে std::variant<>এটির সংজ্ঞাটি যদি ইনস্ট্যান্ট না করা হয় তবে এটি ঠিক আছে
xskxzr
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.