8

考虑这段代码:

#include <variant>

struct x {
  int y;
};

int main() {
  std::variant<x> v(std::in_place_type<x>, {3}); /*1*/
  return std::get<x>(v).y;
}

这不会编译,{}从行中删除时也不会编译/*1*/,即使聚合初始化也是如此

x a{3};
x b({3});

以“类似构造函数”的形式工作。我能否以某种方式使std::variant初始化程序意识到使用聚合初始化构造结构的可能性,而不必为可能在我的实际案例中使用的每个结构编写无聊的样板构造函数?

我希望这能以某种方式工作,根据cppreference有问题的两个重载 (5) 和 (6) 都说

构造具有指定替代 T 的变体并使用参数初始化包含的值[...]

如果这很重要,我正在使用 GCC 7。

4

3 回答 3

3

也许这不是您要问的,但是显式构造对象而不是依赖类型推断呢?

#include <variant>

struct x {
  int y;
};

int main() {
  std::variant<x> v(std::in_place_type<x>, x{3});
  return std::get<x>(v).y;
}
于 2017-10-03T08:52:38.107 回答
2

除了添加构造函数之外,没有解决方法。该标准分别对您提到的[variant.ctor]19[variant.ctor]23两种重载都要求这样做:

效果T:初始化包含的值,就像使用参数直接非列表初始化类型的对象一样std​::​forward<Args>(args)...

效果T:初始化包含的值,就像使用参数直接非列表初始化类型的对象一样il, std​::​forward<Args>(args)...

您始终可以使用以下方法复制或移动对象:

std::variant<x> v(std::in_place_type<x>, x{3});
// or more clear and does the same thing
std::variant<x> v(x{3});
于 2017-10-03T08:52:38.617 回答
0

If you want to go overkill, we can create a factory type that has a conversion operator:

template <class... Args>
struct list_init_from {
    std::tuple<Args...> args;

    template <class T>
    operator T() {
        return std::apply([](auto... args){
            return T{args...};
        }, args);
    }   
};

template <class... Args>
list_init_from(Args... ) -> list_init_from<Args...>;

Which you can use:

std::variant<x> v(std::in_place_type<x>, list_init_from{3});

This works, but leaves much to be desired: perfect forwarding, SFINAE on the conversion operator, and explicitly specifying which types to allow conversions to are exercises left to the reader.

于 2017-10-03T15:47:12.217 回答