std ::在现代C ++中访问有什么问题

适马类型和你


让我们谈谈一个简单而强大的编程概念-sigma类型。

sigma类型(类型总和,标记为并集)可以包含一种值,并且只能包含几种类型之一。 例如,考虑类似INI的配置文件中的设置。 让每个设置为字符串,整数或布尔值。 如果我们想用C ++编写我们的库,我们将编写如下代码:

struct Setting {
    union {
        string str;
        int num;
        bool b;
    };
    enum Type { Str, Int, Bool };
    Type tag;
};

//     
using Settings = unordered_map<string, Setting>;

, :

  • tag .
  • .
  • . string, .

, , . getType(), asBool(), asString(), . , , . .

, - . C++17 ! std::variant, .

std::variant


variant — , , . variant<string, int, bool>. variant :

variant<string, int, bool> mySetting = string("Hello!"); // 
mySetting = 42; // 
mySetting = false;

variant, , , . . , :

match (theSetting) {
    Setting::Str(s) =>
        println!("A string: {}", s),
    Setting::Int(n) =>
        println!("An integer: {}", n),
    Setting::Bool(b) =>
        println!("A boolean: {}", b),
};

C++17(*). std::visit. variant, , -, variant.

-? — , :

struct SettingVisitor {
    void operator()(const string& s) const {
        printf("A string: %s\n", s.c_str());
    }

    void operator()(const int n) const {
        printf("An integer: %d\n", n);
    }

    void operator()(const bool b) const {
        printf("A boolean: %d\n", b);
    }
};

, , - . … . -?

make_visitor(
    [&](const string& s) {
        printf("string: %s\n", s.c_str());
        // ...
    },
    [&](const int d) {
        printf("integer: %d\n", d);
        // ...
    },
    [&](const bool b) {
        printf("bool: %d\n", b);
        // ...
    }
)

, make_visitor, . .

template <class... Fs>
struct overload;

template <class F0, class... Frest>
struct overload<F0, Frest...> : F0, overload<Frest...>
{
    overload(F0 f0, Frest... rest) : F0(f0), overload<Frest...>(rest...) {}

    using F0::operator();
    using overload<Frest...>::operator();
};

template <class F0>
struct overload<F0> : F0
{
    overload(F0 f0) : F0(f0) {}

    using F0::operator();
};

template <class... Fs>
auto make_visitor(Fs... fs)
{
    return overload<Fs...>(fs...);
}

, C++11. , F0, , .

, ! C++17 ,

template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;

, ? , (if constexpr) C++17:

[](auto& arg) {
    using T = std::decay_t<decltype(arg)>;

    if constexpr (std::is_same_v<T, string>) {
        printf("string: %s\n", arg.c_str());
        // ...
    }
    else if constexpr (std::is_same_v<T, int>) {
        printf("integer: %d\n", arg);
        // ...
    }
    else if constexpr (std::is_same_v<T, bool>) {
        printf("bool: %d\n", arg);
        // ...
    }
}

?


std::visit — . : -. , :

  1. , ,
  2. , :
    • ,
    • using- , C++17.


  3. , constexpr if, type_traits, std::decay.

C++-, «» . - , .

?


ISO C++, . , , . , - , . , — - . , … ? ? variant , ? , C++17 , - make_visitor. .

? , . , , SFINAE, - :

template <typename F>
typename std::enable_if<!std::is_reference<F>::value, int>::type
foo(F f)
{
    // ...
}

, std::visit. , , , int string .

, C++ , , . , Effective C++ Effective Modern C++, . , , . , . .

?


, C++ , (*). , . , C++, , C. .

, . D, , . Rust, , unique_ptr shared_ptr ( ), . 2017 , #include.

, , , , , . , . C++ , .

, variant, . - — , . , « , ++».


1. "$\Sigma$-" , . A B, - A B. «» -: -, , .. , A B A B.

2. P0095R1 C++.

3.

Source: https://habr.com/ru/post/zh-CN415737/


All Articles