简体   繁体   English

std::optional 如何从初始值设定项列表中构造 std::variant ?

[英]How does std::optional construct std::variant in place from initializer list?

#include <optional>
#include <variant>
#include <utility>
#include <set>

int main()
{
    std::optional<std::variant<std::pair<int, int>, std::set<int>>> foo(std::in_place, {1, 4});
}
  1. This compiles.这编译。 But how is that possible when std::variant does not have a constructor that takes std::initializer_list<T> as its first argument , but all that this constructor overload of std::optional does is pass the initializer list and forward other arguments to the internal type constructor ?但是,当std::variant没有将std::initializer_list<T>作为其第一个参数的构造函数时,这怎么可能呢,但是std::optional这个构造函数重载所做的只是传递初始化列表并转发其他参数到内部类型构造函数
  2. Which type does the std::variant hold now, std::set or std::pair ? std::variant现在持有哪种类型, std::setstd::pair

It's a bit complicated, so bear with me.这有点复杂,所以请耐心等待。

optional<T> has a constructor that takes an in_place_t and an initializer_list<U> (and optional extra arguments). optional<T>有一个构造函数,它接受一个in_place_t和一个initializer_list<U> (以及可选的额外参数)。 It will then attempt to construct T as if by this statement:然后它将尝试构造T就像通过以下语句一样:

T t(list, ...);

Where list is the initailizer list and ... are any extra arguments.其中list是初始化程序列表,而...是任何额外的参数。

T is of course a variant<pair, set> . T当然是一个variant<pair, set> variant is implicitly convertible from any type V through a template constructor. variant可以通过模板构造函数从任何类型V隐式转换。 However, this constructor only exists if V is a type such that, given a value v of this type, the following is true:然而,只有当V是一个类型时,这个构造函数才存在,这样,给定一个这个类型的值v ,下面是真的:

W w(std::forward<V>(v));

Where W (I'm running out of letters here) is one of the types in the variant . W (我在这里用完了字母)是variant中的类型之一。 Now variant can have multiple types, so variant basically considers all possible W s and their constructor overloads.现在variant可以有多种类型,所以variant基本上考虑了所有可能的W及其构造函数重载。 So long as overload resolution selects exactly one such constructor among all possible W s in the variant , the conversion will work.只要重载决议在所有可能的W variant选择了一个这样的构造函数,转换就会起作用。

pair has no constructor that takes an initializer_list , so none of its constructors count. pair没有带initializer_list构造initializer_list ,所以它的构造函数都不算数。 set<X> has a constructor that takes an initializer_list<X> . set<X>有一个构造函数,它接受一个initializer_list<X>

So, back to the original statement.所以,回到最初的陈述。 Because optional had an initializer_list<Y> parameter where Y is deduced, the braced-init-list will deduce Y as int .因为optional有一个initializer_list<Y>参数,其中Y是推导的,所以花括号初始化器列表会将Y推导为int And int is the same type as the set in the variant .并且intvariantset类型相同。 So set<int> can be constructed from an initailizer_list<int> .所以set<int>可以从initailizer_list<int>构造。

And therefore, that's what gets created in the variant .因此,这就是在variant创建的内容。

If you had a vector<int> as part of the variant , you'd get a compile error due to the ambiguity of which to call.如果你有一个vector<int>作为variant一部分,你会因为调用的不明确而得到一个编译错误。

And there's not really a way to fix that through in_place gymnastics.并没有真正的方法可以通过in_place体操来解决这个in_place You can't do (std::in_place, std::in_place_type<std::set>, {1, 4}) , because the braced-init-list won't get properly deduced.您不能这样做(std::in_place, std::in_place_type<std::set>, {1, 4}) ,因为无法正确推断出花括号初始化器列表。 So you'd have to do (std::in_place, std::set{1, 4}) and let move construction move from the temporary into the variant .所以你必须做(std::in_place, std::set{1, 4})并让移动构造从临时移动到variant

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何使用初始化列表来初始化 std::variant? - How to use initializer list to initialize std::variant? 用 std::initializer_list 构造用 std::optional 包裹的 std::map - Constructing std::map wrapped with std::optional with std::initializer_list 尝试使用初始化列表构造`std :: vector`的问题 - Issues trying to construct `std::vector` with initializer list 是否可以以编程方式构造std :: initializer_list? - Is it possible to programmatically construct a std::initializer_list? 从 std::array 私有继承时无法从 std::initializer_list 构造 - Can't construct from std::initializer_list when privately inheriting from std::array std::visit 如何与 std::variant 一起使用? - How does std::visit work with std::variant? std :: set和std :: unordered_set如何使用emplace()构造元素? - How does std::set and std::unordered_set construct elements in place with emplace()? initializer_list 构造函数以某种方式从 std::variant 构造函数重载集中排除 - initializer_list constructor somehow excluded from std::variant constructor overload set 如何构建 std::vector<std::string> 来自 std::initializer_list<char const*> - How to build std::vector<std::string> from std::initializer_list<char const*> 如何使用 std::shared_ptr 构建结构的 std::optional - How to construct a std::optional of a struct with std::shared_ptr
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM