Из-за скуки и желания некоторой практики (так что, пожалуйста, не говорите мне просто использовать Boost :-)) В настоящее время я использую итератор с подсчетом стиля STL.
Тем не менее, при реализации функций, для которых требуется difference_type
должно быть определено для чего-то значимого, я узнал, что не знаю, что я должен использовать. Сначала я хотел просто использовать любой тип, с которым был построен итератор, но это приводит к очевидным проблемам с неподписанными типами, и просто "Что бы я ни использовал, я использовал ptrdiff_t
", привел бы к потенциальным проблемам при шаблонах с произвольными целыми числами,
В основном мой вопрос сводится к тому, что следует заменить ?
в приведенном ниже коде. (С++ 11 Добро пожаловать, я уже использую static_assert
, noexcept
спецификаторов и такие)
template <typename Num>
class counting_iterator{
typedef Num value_type;
typedef counting_iterator<value_type> iter;
typedef ? difference_type;
/* Constructors, etc omitted for clarity */
difference_type operator-(const iter& rhs) const {
/* Calculate the difference here */
}
};
Подсчет итератора - это своего рода взлом для начала. Весь смысл этого заключается в добавлении оператора * к целым типам. Если это действительно все, для чего они нужны, тогда никто не заботится о том, что такое разница. Если вы хотите, чтобы все было правильно в любом случае, оно должно быть того же типа, когда Num подписан и подписанный тип с хотя бы еще одним битом, если Num - без знака.
Должно быть что-то вроде этого:
template <typename Num, bool IS_SIGNED>
class DifferenceType
{
public:
typedef Num type;
};
template <unsigned DIGITS, bool DIGITS_32_OR_LESS>
class TypeLargerThanImp3
{
public:
typedef int64 type;
};
template <unsigned DIGITS, bool DIGITS_16_OR_LESS>
class TypeLargerThanImp2
{
public:
typedef int32 type;
};
template <unsigned DIGITS>
class TypeLargerThanImp2<DIGITS, false>
{
public:
typedef TypeLargerThanImp3<DIGITS, (DIGITS<=32) >::type type;
};
template <unsigned DIGITS, bool DIGITS_8_OR_LESS>
class TypeLargerThanImp
{
public:
typedef int16 type;
};
template <unsigned DIGITS>
class TypeLargerThanImp<DIGITS, false>
{
public:
typedef TypeLargerThanImp2<DIGITS, (DIGITS<=16) >::type type;
};
template <unsigned DIGITS>
class TypeLargerThan
{
public:
typedef TypeLargerThanImp<DIGITS, (DIGITS<=8) >::type type;
};
template <typename Num>
class DifferenceType<Num, false>
{
public:
typedef TypeLargerThan<std::numeric_limits<Num>::digits>::type type;
};
И ваш тип разницы:
typedef DifferenceType<Num, std::numeric_limits<Num>::is_signed>::type difference_type;
boost::detail::numeric_traits<T>::difference_type
или пользователь может переопределить его. Строго они не получают никакой гарантии, если не указывают тип, так что вы можете сделать свой эквивалент таким хорошим или плохим, как вам нравится. Вы можете просто использоватьint
когда пользователь не указывает, и это их собственная глупая ошибка - ожидать большего ;-)