Как инициализировать счетчик цикла, объявленный с ключевым словом auto? - PullRequest
0 голосов
/ 24 мая 2018

Вот мой код:

#include <iostream>
#include <vector>

void cumulative_sum_with_decay(std::vector<double>& v)
{
    for (auto i = 2; i < v.size(); i++) {
        v[i] = 0.167 * v[i - 2] + 0.333 * v[i - 1] + 0.5 * v[i];
    }
}

void printv(std::vector<double>& v)
{
    std::cout << "{";
    for (auto i = 0; i < v.size() - 1; i++) {
        std::cout << i << ", ";
    }
    std::cout << v[v.size() - 1] << "}\n";
}

int main()
{
    auto v = std::vector<double>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    cumulative_sum_with_decay(v);
    printv(v);
}

Когда я пытаюсь скомпилировать и запустить эту программу, я получаю следующие предупреждения:

$ clang++ -std=c++11 -Wextra foo.cpp && ./a.out
foo.cpp:6:24: warning: comparison of integers of different signs: 'int' and 'std::__1::vector<double,
      std::__1::allocator<double> >::size_type' (aka 'unsigned long') [-Wsign-compare]
    for (auto i = 2; i < v.size(); i++) {
                     ~ ^ ~~~~~~~~
foo.cpp:14:24: warning: comparison of integers of different signs: 'int' and 'unsigned long'
      [-Wsign-compare]
    for (auto i = 0; i < v.size() - 1; i++) {
                     ~ ^ ~~~~~~~~~~~~
2 warnings generated.
{0, 1, 2, 3, 4, 5, 6, 7, 8, 8.68781}

Как я могу инициализировать эти счетчики циклов, объявленные сauto так, что код безопасен и нет предупреждений?

Обратите внимание, что хотя у меня есть небольшой вектор, я пытаюсь научиться писать безопасный код с auto, даже если векторнастолько большое, что значение в i может превышать диапазон целых чисел.

Ответы [ 5 ]

0 голосов
/ 24 мая 2018

Это не ответ на ваш вопрос, но он решает вашу проблему с использованием итераторов.

void cumulative_sum_with_decay(std::vector<double>& v)
{
    assert(v.size()>2);
    for (auto it = v.begin()+2; it!=v.end(); it++) {
        *it =  0.167 * *(it-2) + 0.333 * *(it-1) + 0.5 * *it;
    }
}

void printv(std::vector<double>& v)
{
    assert(v.size()>0);
    std::cout << "{";
    for (auto it = v.begin(); it != v.end() - 1; it++) {
        std::cout << *it << ", ";
    }
    std::cout << v.back() << "}\n";
}

int main()
{
    auto v = std::vector<double>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    cumulative_sum_with_decay(v);
    printv(v);
}
0 голосов
/ 24 мая 2018

Если вы хотите точно подобрать тип, вы можете написать помощника для этого ( живой пример ):

// Concepts would help here.
template<typename Cont, typename T>
auto as_size_type(const Cont& cont, T init) {
    return static_cast<decltype(std::size(cont))>(init);   
}

Использование:

for (auto i = as_size_type(v, 2); i < v.size(); i++) {
    v[i] = 0.167 * v[i - 2] + 0.333 * v[i - 1] + 0.5 * v[i];
}

Я использую std::size для обработки различий, таких как массивы и классы, которые имеют ::size_type, но можно перенести эту ответственность на этого помощника, если std::size недоступен.Аналогичным образом, для автоматического вывода типа возврата можно использовать decltype и т. Д. Вместо этого в C ++ 11.

0 голосов
/ 24 мая 2018
auto i=2 

означает, что a является int типом, а vector.size() является size_t, поэтому пришло -Wsign-сравнение.Вы можете использовать

for (std::size_t i = 0, max = vec.size(); i != max; ++i)

или

for (auto it = vec.begin(), end = vec.end(); it != end; ++it)
0 голосов
/ 24 мая 2018

Вы можете использовать 'decltype (v.size ())', чтобы получить правильный тип.

for (decltype(v.size()) i = 2; i < v.size(); i++) 
0 голосов
/ 24 мая 2018

Тип auto -объявленной переменной выводится из инициализатора.учитывая 2 или 0, это будет int.

. Вы можете указать тип с явно типизированным инициализатором.например,

for (auto i = static_cast<decltype(v.size())>(2); i < v.size(); i++) {
...