Reputation: 392
I have 2 classes, which are both included in variant. The variant is then used in both classes.
template <typename T>
struct Deferred
{
typedef T value_type;
};
template <typename T>
struct DeferredContainer
{
typedef typename T::value_type value_type;
};
class DictionaryObject;
class MixedArrayObject;
using DictionaryObjectPtr = Deferred < DictionaryObject >; // DeferredContainer<DictionaryObject>
using MixedArrayObjectPtr = Deferred < MixedArrayObject >; // DeferredContainer<MixedArrayObject>
typedef boost::variant <
MixedArrayObjectPtr,
DictionaryObjectPtr
> ContainerPtr;
class MixedArrayObject
{
public:
typedef int value_type;
inline void SetContainer(ContainerPtr obj) { _container = obj; }
inline ContainerPtr GetContainer() const { return _container; }
private:
ContainerPtr _container;
};
class DictionaryObject
{
public:
typedef float value_type;
inline void SetContainer(ContainerPtr obj) { _container = obj; }
inline ContainerPtr GetContainer() const { return _container; }
private:
ContainerPtr _container;
};
I don't know exactly how this works, but when I try to expose some properties on either array or dictionary via typedef (and use them in DeferredContainer), I receive error:
error C2602: 'DeferredContainer::value_type' is not a member of a base class of 'DeferredContainer'
Can I make this work somehow? Any other ideas?
Update 31.5, 4:09 PM.
I have reduced the problem to its minimum. Hope this finally gets the attention. The code.
After you switch the MixedArrayObjectPtr to be DeferredContainer, the code won't compile anymore.
Upvotes: 3
Views: 439
Reputation: 303537
I would propose just reordering your code to make sure that all the definitions are in the order that they are used in. We'll have to use Object*
instead of Object
due to the need of variant
to have complete types:
// main types
class Dictionary;
class Array;
template <typename T> struct DeferredContainer;
using DictionaryPtr = DeferredContainer<Dictionary>;
using ArrayPtr = DeferredContainer<Array>;
struct Object;
// now definitions of them
class Dictionary
{
public:
typedef int value_type;
std::map<Name, Object*> list; // note Object*
};
class Array
{
public:
typedef int value_type;
std::vector<Object*> list; // note only one type here
};
template <typename T>
struct DeferredContainer
{
// now can do stuff with T::value_type
};
And after all of that, we can declare Object
. We cannot forward-declare an alias unfortunately, but we can just wrap up the variant
:
struct Object {
boost::variant<
DictionaryPtr,
ArrayPtr
> value;
};
With that ordering, everything compiles.
Upvotes: 3