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?
Derived.hpp
wasn't included and you need a set of boost headers.
This works:
File ./Base.cpp
#include "Base.hpp"
namespace ns {
uint64_t Base::foo() const { return 9; }
} // namespace ns
File ./Base.hpp
#pragma once
#include <cstdint>
namespace ns {
class User;
class Base {
public:
uint64_t foo() const;
};
} // namespace ns
File ./Derived.cpp
#include "Derived.hpp"
namespace ns {
uint64_t Derived::bar() const { return 42; }
} // namespace ns
File ./Derived.hpp
#pragma once
#include "Base.hpp"
namespace ns {
class Derived : public Base {
public:
uint64_t bar() const;
};
} // namespace ns
File ./User.cpp
#include "User.hpp"
namespace ns {
void User::do_something() {
map.emplace(std::make_unique<Derived>());
map.emplace(std::make_unique<Derived>());
}
} // namespace ns
File ./User.hpp
#include "Derived.hpp"
#include "declaration.hpp"
#include <boost/multi_index/mem_fun.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index_container.hpp>
// #include <map>
namespace ns {
namespace bmi = boost::multi_index;
using Map = boost::multi_index_container<
DerivedPtr,
bmi::indexed_by<bmi::ordered_unique<bmi::tag<struct Foo>, //
bmi::const_mem_fun<Base, uint64_t, &Base::foo>>, //
bmi::ordered_non_unique<bmi::tag<struct Bar>, //
bmi::const_mem_fun<Derived, uint64_t, &Derived::bar>> //
>>;
class User {
public:
void do_something();
private:
// std::map<uint64_t, DerivedPtr> map;
Map map;
};
} // namespace ns
File main.cpp
#include "User.hpp"
int main() {
ns::User user;
user.do_something();
};
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>>>>;