void foo()
{
IndexType idx = 10;
OffsetType offs;
offs = idx; // Как сделать, чтобы это было невозможно (носвместимость типов)
// или хотя-бы Warning ?
}
Необязательно именно так, главное чтобы суть идеи сохранилась
Chez, ICQ# 161095094
Re: Жёсткая типизация
От:
Аноним
Дата:
19.10.04 11:38
Оценка:
Здравствуйте, Chez, Вы писали:
C>Приветствую всех!
C>
C>void foo()
C>{
C> IndexType idx = 10;
C> OffsetType offs;
C> offs = idx; // Как сделать, чтобы это было невозможно (носвместимость типов)
C> // или хотя-бы Warning ?
C>}
C> C>Необязательно именно так, главное чтобы суть идеи сохранилась
А в чем суть идеи-то? Можно реализовать TypedCounterType и UntypedCounterType как классы, тогда присваивание по умолчанию работать не будет. typedef не вводит новый тип — только другое имя для уже существующего типа.
C>void foo()
C>{
C> IndexType idx = 10;
C> OffsetType offs;
C> offs = idx; // Как сделать, чтобы это было невозможно (носвместимость типов)
C> // или хотя-бы Warning ?
C>}
C> C>Необязательно именно так, главное чтобы суть идеи сохранилась
только отказаться от typedef и объявить полноценные пользовательские типы
Здравствуйте, <Аноним>, Вы писали:
А>А в чем суть идеи-то? Можно реализовать TypedCounterType и UntypedCounterType как классы, тогда присваивание по умолчанию работать не будет. typedef не вводит новый тип — только другое имя для уже существующего типа.
Хм... Если сделать оператор преобразования типа
class TypedCounterType<size_t id>
{
public:
operator int() { ... };
...
};
// тоtypedef TypedCounterType<0> type1;
typedef TypedCounterType<1> type2;
type1 a;
type2 b;
a = b; // Увы, работает :(
Chez, ICQ# 161095094
Re[3]: Жёсткая типизация
От:
Аноним
Дата:
19.10.04 11:57
Оценка:
Здравствуйте, Chez, Вы писали:
C>Здравствуйте, <Аноним>, Вы писали:
А>>А в чем суть идеи-то? Можно реализовать TypedCounterType и UntypedCounterType как классы, тогда присваивание по умолчанию работать не будет. typedef не вводит новый тип — только другое имя для уже существующего типа.
C>Хм... Если сделать оператор преобразования типа C>
C>void foo()
C>{
C> IndexType idx = 10;
C> OffsetType offs;
C> offs = idx; // Как сделать, чтобы это было невозможно (носвместимость типов)
C> // или хотя-бы Warning ?
C>}
C> C>Необязательно именно так, главное чтобы суть идеи сохранилась
так подойдет? :
#include <iostream>
template <class T, class ID>
class wrap {
typename T data_;
public:
wrap() {}
wrap(const T& init): data_(init) {}
operator typename T() {
return data_;
}
};
typedef wrap<int, class id1> type1;
typedef wrap<int, class id2> type2;
int main() {
type1 a1, b1=5;
type2 a2=1;
a1=b1; // ok
a1=4; // ok
a1=a2; // не компилится
std::cout<<a1<<std::endl;
}
Все это надоть явно перегружать. Это не просто лишняя работа, иногда это приводит в конфликтам с тем же оператором T(). Вообще, для хорошей переносимости не стоит увлекаться перегрузкой операторов и особенно, типа T().
Что и говорить, не хватает в C++ простого добавления новых типов. Что-то типа:
Здравствуйте, McSeem2, Вы писали:
MS>А как насчет: MS>
MS> a1 += 10;
MS> ++a1;
MS>
MS>Все это надоть явно перегружать. Это не просто лишняя работа, иногда это приводит в конфликтам с тем же оператором T(). Вообще, для хорошей переносимости не стоит увлекаться перегрузкой операторов и особенно, типа T().
доработать напильником до полного удовлетворения
MS>Что и говорить, не хватает в C++ простого добавления новых типов. Что-то типа: MS>
Здравствуйте, McSeem2, Вы писали:
MS>Здравствуйте, yxiie, Вы писали:
Y>>Да не говори, все тебе чего-то в С++ нехватает, то типов, то препроцессора.
MS>Не препроцессора, а макро-процессора. Сколько можно талдычить? MS>Препроцессирование как отдельный процесс — маздай.
Думаю макропроцессор от древнего и уже почти забытого PL/1 тебе бы понравился.
В нем есть и свои встроенные типы данных (включая естественно строковые)
и процедуры с функциями и кажется даже операторы ввода/вывода.
В общем на макропроцессоре PL/1 вполне реально писать самые обычные программы.
Здравствуйте, bkat, Вы писали:
B>Думаю макропроцессор от древнего и уже почти забытого PL/1 тебе бы понравился.
Почему "бы"? Именно он мне и нравился Но это было в 85-86 годах прошлого века.
Потом пошел MACRO-11, который был значительно хуже. Потом — сишный, который просто халтура по сравнению с MACRO-11. Такие дела...
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
C>void foo()
C>{
C> IndexType idx = 10;
C> OffsetType offs;
C> offs = idx; // Как сделать, чтобы это было невозможно (носвместимость типов)
C> // или хотя-бы Warning ?
C>}
C> C>Необязательно именно так, главное чтобы суть идеи сохранилась
Для целочисленных проще всего использовать перечисления, приведение enum->integer неявное, а приведение integer->enum явное.
C>void foo()
C>{
C> IndexType idx = 10;
C> OffsetType offs;
C> offs = idx; // Как сделать, чтобы это было невозможно (носвместимость типов)
C> // или хотя-бы Warning ?
C>}
C> C>Необязательно именно так, главное чтобы суть идеи сохранилась
Я, например, иногда в подобных случаях делаю так:
enum TypeCounterType {};
inline TypeCounterType toTypeCounterType(int i) { return static_cast<TypeCounterType>(i); }
// определим нужные нам операторы (их оказывается, как правило, немного)inline TypeCounterType & operator ++ (TypeCounterType & t)
{
return t = toTypeCounterType(t + 1);
}
enum UntypedCounterType {};
Здравствуйте, folk, Вы писали:
F>Здравствуйте, McSeem2, Вы писали:
MS>>Что и говорить, не хватает в C++ простого добавления новых типов. Что-то типа: MS>>
MS>>introduce_type int my_integral;
MS>>
F>Какие операции с my_integral должны унаследоваться от int, а какие нет?
очевидно, все, но с заменой int на my_integral.
и, естественно, запрет неявного преобразования одного в другое.