Скажем, у меня есть класс, представляющий автоматы, состояния которых пронумерованы (using state_t = unsigned
) и чьи транзитоны также пронумерованы (using transition_t = unsigned
). Конечно, в какой-то момент я в конечном итоге messing некоторые звонки, потому что transition_t
и state_t
одного типа, поэтому компилятор не обеспечивает безопасность (семантического) типа. Это легко обойти, используя небольшой класс с шаблоном (struct transition_tag {}; struct state_tag {};
), так что теперь transition_t
и state_t
несовместимы, хорошо!Семантические типы, связанные с компилятором
/// Lightweight state/transition handle (or index).
template <typename Tag>
struct index_t_impl
{
using index_t = unsigned;
constexpr index_t_impl(index_t i)
: s{i}
{}
// Disallow index1_t i{index2_t{42}};
template <typename T>
index_t_impl(index_t_impl<T> t) = delete;
bool operator==(index_t_impl t) const
{
return s == t.s;
}
// Disallow index1_t{42} == index2_t{42};
template <typename T>
bool operator==(index_t_impl<T> t) const = delete;
/// Default ctor to please containers.
index_t_impl() = default;
constexpr operator index_t() const { return s; }
/// Be compliant with Boost integer ranges.
index_t_impl& operator++() { ++s; return *this; }
/// Be compliant with Boost integer ranges.
index_t_impl& operator--() { --s; return *this; }
private:
index_t s;
};
Кроме того, у меня есть две структуры, которые очень похожи друг на друга:
predecessors_t
карты от перехода к переходу его предшественника (в кратчайшему пути). Для эффективности этоstd::vector<transition_t>
.path_t
- это список индексов перехода. Для эффективности этоstd::vector<transition_t>
.
И снова у меня есть эта проблема, что я использую std::vector<transition_t>
для двух совершенно разных целей. Конечно, я мог бы снова ввести обертку с шаблоном, но потом все снова становится грязным. Публичное наследование очень заманчиво (Thou shalt not inherit from std::vector)!
Но на самом деле, я устал от ad-hoc-решений каждый раз, когда хочу вводить новые типы, которые в точности похожи на базовый тип, но просто несовместимы. Есть ли какие-либо рекомендации по этому вопросу? Публичное наследование действительно привлекательно, но разве это не приведет к раздуванию кода с тоннами при дополнительных экземплярах? Может быть, публичная композиция (struct predecessors_t { std::vector<transition_t> v; };
) в соответствии с рекомендациями Crashworks (https://stackoverflow.com/a/4353276/1353549) - лучший вариант, который лучше масштабируется?
Есть ли что-нибудь в поле зрения в будущем на C++ для решения этой проблемы?
Я не знаю об этом идет в стандарте, но вы можете посмотреть здесь: HTTP: // StackOverflow.com/вопросы/28916627/strong-typedefs – Hayt