3

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?

wreckgar23
  • 1,025
  • 9
  • 22
  • I don't need `struct Inner` to get the compilation error ie. if I have a member variable `Outer::state` initialised in the same way, and delete the code for `struct Inner`, I get the same compilation error – wreckgar23 Sep 06 '19 at 10:10

1 Answers1

2

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.

Davis Herring
  • 36,443
  • 4
  • 48
  • 76
  • Thanks. Where CWG2335 says "the function body of compute_right is not supposed to be evaluated until the class is complete", would you know where this evaluation order is defined? – wreckgar23 Sep 06 '19 at 10:21
  • 1
    @wreckgar23: That’s (implied by) [[class.mem]/6](http://eel.is/c++draft/class.mem#6.1), which says that the class is considered to be complete there (and so “forward lookup”—really deferred lookup—can occur). – Davis Herring Sep 06 '19 at 14:17