How can I initialize this std::variant data member which has two similar alternatives?

114 views Asked by At

The following code does not compile. Why is this restriction, and how can I bypass it? If I replace the variant declaration, it compiles.

struct PPP
{
    int xxx;
    PPP() : x(xxx) {} // error: No matching constructor for initialization of 'std::variant<Inner1, Inner2>'

    struct Inner1
    {
        Inner1(int &x )  : c(x) {}
        int &c;
    };
    struct Inner2
    {
        Inner2(int &x )  : c(x) {}
        int &c;
    };
    struct Inner3 {};

    std::variant<Inner1, Inner2> x;
    // std::variant<Inner1, Inner3> x; // This will cause the code to compile
};
1

There are 1 answers

2
Remy Lebeau On

The xxx member is an int.

Inner1 and Inner2 are both constructable from (a reference to) an int, so x(xxx) is ambiguous for std::variant<Inner1, Inner2> as the compiler doesn't know which type you want to construct inside the std::variant.

When you use std::variant<Inner1, Inner3> instead, there is no ambiguity since Inner3 can't be constructed from an int.


UPDATE: As Raymond mentioned in a comment, in this case you can use one of the std::in_place_type_t or std::in_place_index_t constructors of std::variant to tell the compiler which inner type you want to create from the int.