Что такое хороший выбор для подсчета итераторов разности?

0

Из-за скуки и желания некоторой практики (так что, пожалуйста, не говорите мне просто использовать 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 */
    }
};
  • 0
    Я знаю, что вы не хотите, чтобы я просто сказал «использовать Boost», но у Boost уже есть ответ на этот вопрос. Там есть boost::detail::numeric_traits<T>::difference_type или пользователь может переопределить его. Строго они не получают никакой гарантии, если не указывают тип, так что вы можете сделать свой эквивалент таким хорошим или плохим, как вам нравится. Вы можете просто использовать int когда пользователь не указывает, и это их собственная глупая ошибка - ожидать большего ;-)
  • 0
    Если нет никакого реального ответа, не зная Num, тогда позвольте клиентскому коду указать тип_различия. Если вы хотите догадаться об этом, используйте какие-то черты типа (таким образом, вы можете получить ошибку, если она не известна как адекватная, но клиенты все еще могут легко добавить поддержку для своих собственных типов), или если вам повезет, просто например, выберите по умолчанию int64_t - он, вероятно, будет в порядке на 99,9% от времени и сделает использование более удобным.
Показать ещё 5 комментариев
Теги:
stl

1 ответ

1

Подсчет итератора - это своего рода взлом для начала. Весь смысл этого заключается в добавлении оператора * к целым типам. Если это действительно все, для чего они нужны, тогда никто не заботится о том, что такое разница. Если вы хотите, чтобы все было правильно в любом случае, оно должно быть того же типа, когда 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;
  • 1
    Проголосовали, но не примут, потому что типы фиксированной ширины просто не будут работать для этого. (См. Обсуждение)

Ещё вопросы

Сообщество Overcoder
Наверх
Меню