#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});
}
Run Code Online (Sandbox Code Playgroud)
std::variant 没有构造函数std::initializer_list<T>作为其第一个参数,而这个构造函数重载std::optional所做的只是传递初始化列表并将其他参数转发给内部类型构造函数时,这怎么可能呢?std::variant现在持有哪种类型,std::set还是std::pair?这有点复杂,所以请耐心等待。
optional<T>有一个接受 anin_place_t和 an initializer_list<U>(以及可选的额外参数)的构造函数。然后它将尝试T按照以下语句进行构造:
T t(list, ...);
Run Code Online (Sandbox Code Playgroud)
list初始化程序列表在哪里以及...任何额外的参数。
T当然是一个variant<pair, set>. variant可以V通过模板构造函数从任何类型隐式转换。但是,此构造函数仅在以下情况下才存在V: 给定此类型的值v,以下为真:
W w(std::forward<V>(v));
Run Code Online (Sandbox Code Playgroud)
其中W(我这里的字母用完了)是variant. 现在variant可以有多种类型,因此variant基本上考虑了所有可能的Ws 及其构造函数重载。只要重载决策W在 中所有可能的 s中准确地选择一个这样的构造函数variant,转换就会起作用。
pair没有采用 的构造函数initializer_list,因此它的构造函数都不算数。set<X>有一个采用initializer_list<X>.
那么,回到最初的说法。因为optional有一个initializer_list<Y>参数 whereY被推导,所以 braced-init-list 将推导Y为int。并且与中的int类型相同。因此可以从.setvariantset<int>initailizer_list<int>
因此,这就是在variant.
如果你有一个vector<int>作为 的一部分variant,你会因为调用的不明确性而得到一个编译错误。
并没有真正的方法可以通过in_place体操来解决这个问题。你不能这样做(std::in_place, std::in_place_type<std::set>, {1, 4}),因为花括号初始化列表将无法正确推导。因此,您必须让(std::in_place, std::set{1, 4})移动施工从临时移动到variant.
| 归档时间: |
|
| 查看次数: |
179 次 |
| 最近记录: |