c++boostboost-multi-index

C++ incomplete type used in nested name specifier when using boost::multi_index


I have the following files:

"declaration.hpp"

namespace ns {
    
class Derived;
using DerivedPtr = std::unique_ptr<Derived>;
 
}

"Base.hpp"

namespace ns {

class User;

class Base
{
public:
    uint64_t foo() const;
};

}

"Derived.hpp"

namespace ns {

class Derived : public Base
{
public:
    uint64_t bar() const;
};

}

"User.hpp"

#include "declaration.hpp"
namespace ns {
class User
{
private:
    std::map<uint64_t, DerivedPtr>  map;
};

}

I tried to change the map in User to be a multi index map, i.e in "declaration.hpp" I put

struct Foo{};
struct Bar{};
  
using Map = boost::multi_index_container<
        DerivedPtr,
        boost::multi_index::indexed_by<
            boost::multi_index::ordered_unique<boost::multi_index::tag<Foo>,
                boost::multi_index::const_mem_fun<Base, uint64_t, &Base::foo> >,
            boost::multi_index::ordered_non_unique<boost::multi_index::tag<Bar>,
                boost::multi_index::const_mem_fun<Derived, uint64_t, &Derived::bar> > > >;

and

#include "declaration.hpp"
namespace ns {
class User
{
private:
    Map  map;
};

}

but I get error: incomplete type 'ns::Derived' named in nested name specifier . I can't put #include "Derived.hpp" & #include "Base.hpp" in "declaration.hpp" because then I get error: member access into incomplete type due to the forward declaration in "Base.hpp".

Is there a way to achieve what I'm trying to do? Is it possible to use fixed values for indices, thus eliminating the need for the member functions?


Solution

  • Derived.hpp wasn't included and you need a set of boost headers.

    This works:

    Live On Compiler Explorer

    BONUS: C++17 key extraction

    Live On Compiler Explorer

    using Map     = boost::multi_index_container<
        DerivedPtr,
        bmi::indexed_by<bmi::ordered_unique<bmi::tag<struct Foo>, bmi::key<&Base::foo>>,
                        bmi::ordered_non_unique<bmi::tag<struct Bar>, bmi::key<&Derived::bar>>>>;