Tuesday, May 18, 2010

О велосипедах


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

А так велосипед. Есть вариант покороче?

5 comments:

  1. А чего ты хотел добиться? Компилируемость кода только при передачи в A::B<> типа X?

    ReplyDelete
  2. Именно. Compile-time защита от подсовывания неподходящих вещей. В идеале нужно было разрешить не единственный тип, а набор типов из некоторого тайплиста.

    ReplyDelete
  3. Тогда достаточно того, что ты внутри структуры A написал в первом варианте. Даже сама A не нужна. Нпример, тоже самое через функцию

    ReplyDelete
  4. В том-то и дело, что для сущностей, определяемых внутри класса (в смысле - в его скоупе) запрещена частичная специализация.

    Первый вариант в моём посте - не валидный C++ код. Он просто не компилируется. Твой вариант через функцию вполне рабочий (чего бы ему не работать?), но эта функция находится не внутри класса. А запихать её внутрь класса не получится :-)

    Но даже если бы можно было её туда запихать, этот подход требует вызова твоей функции, в коде, который гарантированно должен будет откомпилироваться при инстанциировании B. Если, например, ты просто добавишь в класс B функцию dummy, которая будет дёргать allow_type(), это не даст гарантии, что B будет успешно инстанциироваться только для типа, который разрешает allow_type, т.к. у компилятора есть право полностью игнорировать код, который не используется после инстанциирования шаблона.

    В микрософтовском копиляторе вообще можно внутри dummy() написать wtiuyeortuieyrotui, компиляция будет успешной пока dummy() никто не использует.

    С другой стороны, когда ты наследуешься от какого-то класса, этот класс обязан быть определён, поэтому решение с наследованием точно будет всегда работать.

    ReplyDelete
  5. Не хочется спорить по мелочам.
    Внимания на ошибке в твоём первом варианте я не стал заострять. Делается так.
    Частичная специализация здесь нигде не нужна.
    Можно сделать и через наследование. В данном примере сам класс A может быть реализован так же, как TypeCheck. Всё зависит от задачи.

    ReplyDelete