Ответ 1
Может быть, форма BOOST_STRONG_TYPEDEF boost/strong_typedef.hpp поможет.
Я хочу объявить свои собственные числовые типы, точно так же, как unsigned int, но я не хочу, чтобы типы были неявно преобразованы. Я попробовал это первым: typedef unsigned int firstID; typedef unsigned int secondID;
но это нехорошо, поскольку два типа являются просто синонимами для unsigned int, поэтому они свободно взаимозаменяемы.
Мне бы хотелось, чтобы это вызвало ошибку:
firstID fid = 0;
secondID sid = fid; // no implicit conversion error
но это будет хорошо:
firstID fid = 0;
secondID sid = static_cast<secondID>(fid); // no error
Моя причина в том, что аргументы функции строго типизированы, например:
void f( firstID, secondID ); // instead of void f(unsigned int, unsigned int)
Каков механизм, который я ищу?
Спасибо
Si
Может быть, форма BOOST_STRONG_TYPEDEF boost/strong_typedef.hpp поможет.
Как вы отметили: typedef плохо назван (он должен быть typealias (D имеет явно добавленные типы (последний раз, когда я смотрел))
Таким образом, единственный способ сделать это - создать два уникальных класса.
Я не собираюсь говорить, что вы не можете написать специализацию static_cast < > , чтобы делать то, что вы хотите, но я думаю (и я еще не так много думал об этом), так что было бы плохой идеей (даже если это юридический), я думаю, что лучший подход заключается в том, чтобы каждый конструктор классов использовал unsigned int, которые явны (поэтому нет автоматического преобразования).
struct FID
{
explicit FID(unsigned int v): value(v) {}
operator unsigned int() {return value;}
unsigned int value;
};
class SID {/* Stuff */};
FID fid(1U);
SID sid(2U);
doSomthingWithTwoSID(sid,SID(static_cast<unsigned int>(fid));
Создание явного конструктора означает отсутствие автоматического преобразования между типами.
Добавив встроенный оператор литья в unsigned int, вы можете использовать его везде, где ожидается int.
Вам нужно написать свои собственные классы для них, переопределяя все необходимые вам операторы.
Ахх, путешественник из Ады, которого я вижу.
Единственный реальный способ сделать это в С++ - объявлять классы. Что-то вроде:
class first_100 {
public:
explicit first_100(int source) {
if (source < 1 || source > 100) {
throw range_error;
}
value = source;
};
// (redefine *all* the int operators here)
private:
int value;
};
Вы захотите определить свой конструктор int explicit
, чтобы С++ не использовал его для неявного преобразования между вашими типами. Таким образом это не сработает:
first_100 centum = first_100(55);
int i = centum;
но что-то вроде этого (если вы его определяете):
int i = centum.to_int();
struct FirstID { int id; };