Ответ 1
Короткий ответ на первый вопрос в тексте: вы должны заменить /*TODO*/
на unsigned
, std::size_t
или что-то подобное, что означает: не надо выводить тип, просто выберите тип, подходящий для любого разумного размера контейнера.
Это будет неподписанный, достаточно большой тип, поэтому у компилятора не будет соблазна кричать на вас о возможных потерях точности. В комментариях выше вы пишете, что size_t
не гарантирует хорошую замену decltype(c.size())
, но в то время как реализовать контейнер с индексом, несовместимым с size_t
, не представляется возможным, такие индексы, безусловно, не будут числа (и, следовательно, несовместимы с i = 0
), и контейнеры не будут иметь также метод size
. Метод A size()
подразумевает неотрицательный интеграл, и поскольку size_t
предназначен для точных этих чисел, почти невозможно будет иметь контейнер размером, который не может быть представлен им.
Ваш второй вопрос направлен на то, как вывести тип, и вы уже предоставили самые легкие, но несовершенные ответы. Если вы хотите, чтобы решение было не таким подробным, как decltype
и не удивительно читать как auto end
, вы могли бы определить псевдоним шаблона и функцию генератора для начального индекса в каком-либо заголовке утилиты:
template <class T>
using index_t = decltype(std::declval<T>().size());
template <class T, class U>
constexpr index_t<T> index(T&&, U u) { return u; }
//and then in the actual location of the loop:
for (auto i = index(c,0); i < c.size(); ++i) {...}
//which is the same as
for (auto i = index_t<std::vector<int>>(0); i < c.size(); ++i) {...}
Если вы хотите иметь более общий индексный тип, например. для массивов и классов, которые не имеют метода size
, он становится немного сложнее, потому что псевдонимы шаблонов не могут быть специализированными:
template <class T>
struct index_type {
using type = decltype(std::declval<T>().size());
};
template <class T>
using index_t = typename index_type<T>::type;
template <class T, class U>
constexpr index_t<T> index(T&&, U u) { return u; }
//index_type specializations
template <class U, std::size_t N>
struct index_type<U[N]> {
using type = decltype(N);
};
template <>
struct index_type<System::AnsiString::AnsiString> { //YUCK! VCL!
using type = int;
};
Однако, это много всего лишь для тех случаев, когда вам действительно нужен индекс, а простой цикл foreach недостаточен.