У меня есть эта головоломка, которую я пытаюсь решить, и она сводится к следующему примеру:
template <typename CT>
struct A
{
typedef typename CT::VALUE_T FOO; // FOO is dependent on CT
};
template <typename CT>
struct B
{
typedef typename CT::BAR BAR;
BAR foo() {}
};
template <typename DT>
struct C : B<C<DT> >
{
typedef DT VALUE_T;
typedef typename A<C>::FOO BAR;
};
int main () {
C<int> c;
}
Я могу попытаться объяснить вышеизложенное (я пробовал три раза и удалил текст!), Но в основном требования:
C
должно наследоваться от B
, введенного с помощью C
(с использованием CRTP), т.е. B<C<>>
C
- единственный, кто может создать экземпляр A
(т. Е. A
должен быть набран с помощью C
)
A
является единственным, который может определить FOO
(FOO
зависит от типа CT
, связь более сложная, чем представленная)
Проблема (как вы можете видеть из приведенного выше кода) заключается в том, что тип BAR
доступен только в пределах C
, и это неполно, когда создается экземпляр B
, следовательно, B
не видит BAR
тип аргумента шаблона CT
(C<int>
). К сожалению, в B
тип BAR
используется в качестве аргументов функций и возвращаемых типов (т. Е. Не ограничивается только областью действия функции - в результате я не могу просто переместить typedef в область действия функции).
Есть ли способ обойти это? Я не могу разорвать вышеуказанные отношения (кроме как в крайнем случае). Предположительно с c ++ 11 я мог бы использовать auto
и обойти необходимость иметь BAR
typedef в B
, однако в настоящее время это еще не вариант.
РЕДАКТИРОВАТЬ: после комментария @bitmasks, еще немного информации.
- Код в
A
и B
используется в нескольких двоичных файлах в различных ситуациях, единственная уникальная ситуация в этом случае состоит в том, что C
происходит от B
, в других случаях C
владеет экземпляром чего-то, полученного из B
.
- Аргументы шаблона могут быть изменены (в
A
и B
), при условии, что они могут быть установлены по умолчанию в значения, которые не требуют изменения существующих применений A
и B
. Тот же набор типов должен быть доступен либо в качестве параметра шаблона по умолчанию, либо в другом механизме.
Я использую шаблоны здесь просто потому, что мне нужна тесная связь, и мне нужна была гибкость, чтобы использовать код в различных ситуациях.
Описание компонентов:
A
лучше всего описать как контейнер, а FOO
на самом деле является итератором, его содержимое определяется typedef параметра шаблона
B
лучше всего описать как базовый класс, который содержит набор функций, которые вызываются некоторыми компонентами , принадлежащими экземпляру C
. В предыдущих случаях этим компонентам передавалась ссылка на вещи, полученные из B
(а эти вещи также принадлежат C
), в данном случае я предоставляю ссылку на C
сама.
Основным осложнением является доступ к контейнеру A
, ранее отношения между B
и C
заключались в том, что C
имеет экземпляр из B
, но теперь C
является экземпляром из B
- это изменение семантики нарушает способ, которым типы вводятся в классы.