我如何消除构造函数调用的initializer_lists的歧义?



我希望能够用大括号初始化container,而不必指定类型。这是更困难的,因为我有嵌套的初始化式。现在我几乎可以工作了,但是在变体包装器中initializer_list有两个重载,编译器无法确定使用哪个。

实际上,在这种情况下,调用甚至没有二义性,因为只有类keyval将字符串作为其第一个参数,这意味着应该选择变体包装器的keyval重载。但是我怎么告诉编译器呢?

My code (CompilerExplorer):

#include <string>
#include <variant>
template <typename... T> struct vwrapper;
using val = vwrapper<std::monostate, struct array, struct obj, int, bool>;
template <typename... T>
struct vwrapper : public std::variant<T...>
{
vwrapper(int);
vwrapper(bool);
vwrapper(std::initializer_list<struct keyval>);
vwrapper(std::initializer_list<val>);
// vwrapper(obj);
// vwrapper(array);
vwrapper(std::monostate);
};
struct obj
{
obj() = default;
obj(std::initializer_list<struct keyval> init) {
}
};
struct array
{
array() = default;
array(std::initializer_list<val> init) {
}
};
struct keyval
{
keyval() = default;
keyval(std::string, val);
};
template <typename... T>
vwrapper<T...>::vwrapper(int) {}
template <typename... T>
vwrapper<T...>::vwrapper(bool) {}
template <typename... T>
vwrapper<T...>::vwrapper(std::initializer_list<val>) {}
template <typename... T>
vwrapper<T...>::vwrapper(std::initializer_list<struct keyval>) {}
// template <typename... T>
// vwrapper<T...>::vwrapper(obj) {}
// template <typename... T>
// vwrapper<T...>::vwrapper(array) {}
keyval::keyval(std::string str, val value) {  }
struct container : public array, public obj
{
using array::array;
using obj::obj;
};

int main()
{
container some_container = { 1, 2, true, false, 2, { { "hello", 2 }, { "mogli", true }}};
}

代码段的最小版本是

#include<initializer_list>
struct val
{
val(int);
val(bool);
val(std::initializer_list<struct keyval>);
val(std::initializer_list<val>);
};
struct keyval
{
keyval(const char*, val);
};
struct container
{
container(std::initializer_list<val>);
container(std::initializer_list<keyval>);
};
void foo()
{
container{{"", 2}, {"", true}};
}
在这一点上,歧义出现了:字符串字面值可以转换为boolval{"", 2}keyval{"", 2}都是有效表达式,第一个被解释为
val{std::initializer_list<val>{val{bool("")}, val{2}}}

为避免歧义,强制类型为keyval

container{keyval{"", 2}, {"", true}};

最新更新