Как сломать этот круговой typedef? - PullRequest
7 голосов
/ 13 ноября 2010

Я хочу объявить пару типов (внутренний для класса, настроенного на K и V и обеспечивающего некоторое поведение кэширования):

typedef std::map<
  long long,
  typename key_to_value_type::iterator  // Ooops... not declared yet
> timestamp_to_key_type;

typedef std::map<
  K,
  std::pair<V,typename timestamp_to_key_type::iterator> 
> key_to_value_type;

Конечно, это невозможно как есть, из-за кругового определения. Я мог бы взломать его с помощью void*, но мне интересно, есть ли какая-нибудь магия предварительного объявления или другая техника, которая сделает работу лучше.

(Да, я знаю, что boost::bimap обойдет проблему).

Ответы [ 2 ]

7 голосов
/ 13 ноября 2010

Это невозможно, подумайте, какими будут типы:

timestamp_to_key_type
= map< long long, key_to_value_type::iterator >
= map< long long, map< K, pair< V, timestamp_to_key_type::iterator > >::iterator >
= map< long long, map< K, pair< V, map< long long, map< K, pair< V, map< long long, map< K, pair < V ...

Это не проблема с предварительными объявлениями, вы просто пытаетесь описать тип, который рекурсивно определен для самого себя.Он ничем не отличается от:

struct A { B b; };
struct B { A a; };

Единственный способ обойти это - потерять некоторую информацию статического типа.Как вы сказали, вы можете использовать void*, или вы можете попытаться определить свой собственный абстрактный, стертый интерфейс.Ваш выбор.

1 голос
/ 13 ноября 2010

Разбейте циклическое определение только одним из них, содержащим V, а другим - итератором:

typedef map<K, V> KVMap;
typedef map<long long, typename KVMap::iterator> TSMap;

Если вам нужно использовать ключ для поиска метки времени, а эта метка времени несохраненный в V, вы можете скопировать его в KVMap:

typedef map<K, pair<V, long long> > KVMap;

Из K вы можете использовать KVMap :: find, получить метку времени, а затем использовать TSMap :: find и получить дескриптор насоответствующий элемент (например, чтобы стереть его).

...