2015-01-21 2 views
3

У меня есть 2 класса, которые включены в вариант. Вариант затем используется в обоих классах.Циркулярная зависимость с полной информацией о типе

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; 
}; 

Я не знаю точно, как это работает, но когда я пытаюсь раскрыть некоторые свойства на любом массиве или словаре через ЬурейеЕ (и использовать их в DeferredContainer), я получаю сообщение об ошибке:

error C2602: 'DeferredContainer::value_type' is not a member of a base class of 'DeferredContainer'

Могу ли я сделать эту работу как-то? Любые другие идеи?


Обновление 31.5, 16:09.

Я уменьшил проблему до минимума. Надеюсь, это, наконец, привлечет внимание. code.

После того, как вы переключите MixedArrayObjectPtr на DeferredContainer, код больше не будет компилироваться.

+0

Как будет объявлен «T :: value_type» внутри T? – Quentin

+0

Во-первых, 'Dictionary' не имеет определения для' value_type'. Также 'Array', поэтому ваш' typedef' в 'DeferredContainer', вероятно, вызовет несколько проблем. – frasnian

+0

Что вы пытаетесь сделать? Можете ли вы нарисовать схему того, что содержит то, что и что указывает на что? –

ответ

3

Я хотел бы предложить только переназначения свой код, чтобы убедиться, что все эти определения в том порядке, что они используются в Придётся использовать Object* вместо Object в связи с необходимостью variant иметь полные типов:.

// 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 
}; 

И после всего этого, мы можем объявить Object. Мы не можем вперед объявить псевдоним, к сожалению, но мы можем просто обернуть variant:

struct Object { 
    boost::variant< 
     DictionaryPtr, 
     ArrayPtr 
    > value; 
}; 

С этой упорядоченности, все компилируется.

+0

Он компилируется, но теперь клиент отвечает за время жизни этих 'Object' s, которое использовалось со значением семантики в исходном проекте. Возможно, 'unique_ptr ' будет лучшим выбором, но я не уверен. Я все еще смущен значением 'DictionaryPtr' и' ArrayPtr', которые для меня не похожи на типы указателей (типа). –

+0

Вы сделали объект необработанным указателем вместо значения. Кто будет ответственен за свободу памяти? Скажем, я хотел бы, чтобы Object был умным указателем, потому что это была вторая цель моего DeferredContainer, была поддержана intrusive_ptr. Я не считал это важным, поэтому я оставил это для демонстрации – Gotcha

+0

Вторая важная вещь: тип T :: value_type для Object пуст и не распространяется значение value_type, заданное ни в массиве, ни в словаре. – Gotcha