struct X {};
struct A {
template<class T>
struct B;
template<>
struct B<X> {};
};
int main() {
typedef A::B<X> b_t;
b_t b;
return 0;
}
Вот по какой-то причине так нельзя.
template<class T1, class T2>
struct Helper;
template<class T>
struct Helper<T, T> {};
struct X {};
struct A {
template<class T>
struct B : public Helper<T, X> {};
};
int main() {
typedef A::B<X> b_t;
b_t b;
return 0;
}
А так велосипед. Есть вариант покороче?
А чего ты хотел добиться? Компилируемость кода только при передачи в A::B<> типа X?
ReplyDeleteИменно. Compile-time защита от подсовывания неподходящих вещей. В идеале нужно было разрешить не единственный тип, а набор типов из некоторого тайплиста.
ReplyDeleteТогда достаточно того, что ты внутри структуры A написал в первом варианте. Даже сама A не нужна. Нпример, тоже самое через функцию
ReplyDeleteВ том-то и дело, что для сущностей, определяемых внутри класса (в смысле - в его скоупе) запрещена частичная специализация.
ReplyDeleteПервый вариант в моём посте - не валидный C++ код. Он просто не компилируется. Твой вариант через функцию вполне рабочий (чего бы ему не работать?), но эта функция находится не внутри класса. А запихать её внутрь класса не получится :-)
Но даже если бы можно было её туда запихать, этот подход требует вызова твоей функции, в коде, который гарантированно должен будет откомпилироваться при инстанциировании B. Если, например, ты просто добавишь в класс B функцию dummy, которая будет дёргать allow_type(), это не даст гарантии, что B будет успешно инстанциироваться только для типа, который разрешает allow_type, т.к. у компилятора есть право полностью игнорировать код, который не используется после инстанциирования шаблона.
В микрософтовском копиляторе вообще можно внутри dummy() написать wtiuyeortuieyrotui, компиляция будет успешной пока dummy() никто не использует.
С другой стороны, когда ты наследуешься от какого-то класса, этот класс обязан быть определён, поэтому решение с наследованием точно будет всегда работать.
Не хочется спорить по мелочам.
ReplyDeleteВнимания на ошибке в твоём первом варианте я не стал заострять. Делается так.
Частичная специализация здесь нигде не нужна.
Можно сделать и через наследование. В данном примере сам класс A может быть реализован так же, как TypeCheck. Всё зависит от задачи.