适马类型和你
让我们谈谈一个简单而强大的编程概念-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>;
, :
, , .
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.