Search code examples
c++c++17inner-classesboost-variant

`constructor required before non-static data member` - Am I hitting c++ core issue 1360 with a `boost::variant`?


With this code

#include <boost/variant.hpp>
#include <string>

struct Outer
{
    struct StateA
    {
        std::size_t index = std::string::npos;
    };

    struct StateB {};

    using State = boost::variant<StateA, StateB>;

    struct Inner
    {
        State state = StateB{};
    };
};

int main() {
    Outer o;
    (void)o;
}

I get the following compilation error

/usr/include/boost/variant/variant.hpp:1301:17:   required from ‘class boost::variant<Outer::StateA, Outer::StateB>’
inner_class.cpp:18:30:   required from here
/usr/include/boost/type_traits/has_nothrow_constructor.hpp:27:84: error: constructor required before non-static data member for ‘Outer::StateA::index’ has been parsed
 template <class T> struct has_nothrow_constructor : public integral_constant<bool, BOOST_HAS_NOTHROW_CONSTRUCTOR(T)>{};

Referring to this question, it would seem that I'm hitting this core issue, but I wanted to check my understanding.

Specifically, am I hitting

an order dependency that is not specified in the current text

when my typedef of a variant is initialised in Inner? Or is there something else about inner structs that causes this compilation error?


Solution

  • This doesn’t depend on anything being (found to be) constexpr, so it’s not identical to CWG1360, but it’s certainly similar in that it capitalizes on the impossibility of simultaneously having a nested class being a complete-class context for its containing class and having the nested class be complete later in the containing class than its definition. Perhaps the best locus is CWG2335, for which the general (long-term) proposal has been made that actual dependencies within a class should be tracked by an instantiation-like mechanism; examples like yours ask for such a treatment across classes.