Sigma Typ und du
Lassen Sie uns über ein einfaches, aber leistungsstarkes Programmierkonzept sprechen - Sigma-Typen.
Ein Sigma-Typ (Typensumme, beschriftete Vereinigung) kann Werte von einem und nur einem von mehreren Typen enthalten. Betrachten Sie beispielsweise die Einstellungen in einer 
INI-ähnlichen Konfigurationsdatei. Jede Einstellung sei eine Zeichenfolge, eine Ganzzahl oder ein Boolescher Wert. Wenn wir unsere Bibliothek in C ++ erstellen wollten, würden wir ungefähr so schreiben:
struct Setting {
    union {
        string str;
        int num;
        bool b;
    };
    enum Type { Str, Int, Bool };
    Type tag;
};
//     
using Settings = unordered_map<string, Setting>;
, :
, , . 
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 — . : -. , :
- , , 
- , :
 
 
 
- , 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. "

-" , . A B, - 
A B. «» -: 
-, , .. , A B 
A B.
2. 
P0095R1 C++.
3.