рд╕рд┐рдЧреНрдорд╛ рдЯрд╛рдЗрдк рдФрд░ рдЖрдк
рдЖрдЗрдП рдПрдХ рд╕рд░рд▓ рд▓реЗрдХрд┐рди рд╢рдХреНрддрд┐рд╢рд╛рд▓реА рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рдЕрд╡рдзрд╛рд░рдгрд╛ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░рддреЗ рд╣реИрдВ - рд╕рд┐рдЧреНрдорд╛ рдкреНрд░рдХрд╛рд░ред
рдПрдХ рд╕рд┐рдЧреНрдорд╛ рдкреНрд░рдХрд╛рд░ (рдЯрд╛рдЗрдк-рд╕рдо, рд▓реЗрдмрд▓ рдпреВрдирд┐рдпрди) рдореЗрдВ рдПрдХ рдФрд░ рдХрдИ рдкреНрд░рдХрд╛рд░реЛрдВ рдореЗрдВ рд╕реЗ рдХреЗрд╡рд▓ рдПрдХ рдХрд╛ рдорд╛рди рд╣реЛ рд╕рдХрддрд╛ рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП,
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.