Type Sigma et vous
Parlons d'un concept de programmation simple mais puissant - les types sigma.
Un type sigma (somme de type, union étiquetée) peut contenir des valeurs d'un et d'un seul parmi plusieurs types. Par exemple, considérez les paramètres dans un fichier de configuration de
type INI . Soit chaque paramètre une chaîne, un entier ou une valeur booléenne. Si nous voulions créer notre bibliothèque en C ++, nous écririons quelque chose comme ceci:
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.