Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
IdOf() : value_() {}
IdOf() = delete;
Отсекаем ошибки программиста или проблемы с вниманием/памятью программиста — заставляем его обязательно задать идентификатор.
INVALID_ID или работают с boost::optional.Не все поймут, почему именно шаблоны лучше, чем ветка наборов таких классов.
explicit IdOf(repr_type value = repr_type()) : value_(value) {}
#include <functional>
struct IdHasher {
template <typename ModelType, typename ReprType>
size_t operator()(const IdOf<ModelType, ReprType> &id) const {
std::hash<ReprType> h;
return h(id.value());
}
};
// Usage example:
#include <unordered_map>
template <typename ModelType>
using IdToModel = std::unordered_map<IdOf<ModelType>, ModelType, IdHasher>;
#include <iostream>
#include <iomanip>
#include <climits>
using namespace std;
template<class Tag, class Base = int> struct def_enum
{
enum class type : Base { }; // Base задаёт ёмкость типа; можно сделать через пару минимум-максимум
};
// тэги типов
struct X;
struct Y;
// искомые типы
typedef def_enum<X>::type XT;
typedef def_enum<Y>::type YT;
int main()
{
XT x = XT(123), z = XT(456);
YT y = YT(123);
cout << (int)x << endl;
cout << (int)y << endl;
cout << boolalpha << (x==z) << endl;
cout << boolalpha << ((int)x == (int)y) << endl;
// cout << x << y << (x==z) << (x==y) << endl;
// ошибки: нет подходящих операторов для (cout << x) и (x==y)
}
template<class Tag> struct IdOf { int value; };
template<class Tag> IdOf<Tag> idof(int value) { IdOf<Tag> v = {value}; return v; }
....
IdOf<Widget> w;
....
w = idof<Widget>(123);
К тому же, явно определённые конструкторы — формально ломают POD.К слову, начиная с C++11, требования заметно ослабили: например, теперь можно и пользовательские конструкторы (главное, чтобы дефолтный конструктор, деструктор, а также конструкторы и операторы копирования и перемещения были тривиальными), члены данных не обязаны быть
public (но все должны иметь одинаковую категорию видимости), разрешено наследование в ограниченном объеме (члены данных могут быть определены только в одном классе из иерархии).
Типобезопасные идентификаторы и фантомные типы