Re: C++ идея для стандарта.
От: rg45 СССР  
Дата: 02.03.18 15:50
Оценка: 12 (2) +3
Здравствуйте, pkl, Вы писали:

pkl>Есть 3 контейнера: a, b, c. Хочу запустить 1 range-цикл по ним всем одновременно:


pkl>
pkl>for( auto i1 : a, auto i2 : b, auto i3 : c) {
    
pkl>}
pkl>

pkl>На каждой итерации i1, i2, i3 имеет очередное значение из соответствующего контейнера.
pkl>Цикл помирает как только исчерпается самый мелкий контейнер.
pkl>Жопа ли это? Я тупой наркоман? Можно ли это сделать уже щас без вундервафлинга?

Это делается элементарно и смысла тащить это в стандарт лично я не вижу. Тут уже вспоминали про zip. Еще можно было бы вспомнить некоторые полезности из boost, такие как iterator_range, iterator_facade, iterator_adaptor.

Но сейчас я хочу показать, как достаоточно просто эта задача решается средсдтвами самого языка, без использования всего перечисленного:

https://ideone.com/HkybcL

#include <functional>
#include <numeric>
#include <iostream>
#include <tuple>
#include <vector>

template <typename...T>
class ZipIterator
{
public:

   using reference = std::tuple<decltype(*std::declval<T>())...>;

public:

   ZipIterator(T&&...i) : m(std::forward<T>(i)...) { };

   reference operator * () const { return std::tie(*std::get<T>(m)...); }
   ZipIterator operator ++ () { char c[]{ (++std::get<T>(m), 0)... }; return *this; }

   bool operator == (const ZipIterator& other) const {
      const bool eq[]{ (std::get<T>(m) == std::get<T>(other.m))... };
      return std::accumulate(std::begin(eq), std::end(eq), false, std::logical_or<>());
   }
   bool operator != (const ZipIterator& other) const { return !(*this == other); }

private:
   std::tuple<T...> m;
};

template <typename T>
struct IteratorRange
{
   T m_begin;
   T m_end;

   const T& begin() const { return m_begin; }
   const T& end() const { return m_end; }
};

template <typename...T>
using ZipRange = IteratorRange<ZipIterator<decltype(std::begin(std::declval<T>()))...>>;

template <typename...T>
ZipRange<T...> make_zip_range(T&&...t) { return {{std::begin(t)...},{ std::end(t)...} }; }

int main()
{
   std::vector<int> a { 1, 2, 3 };
   std::vector<std::string> b { "hello", "world", "foo", "bar" };
   int c[] { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };

   for (auto&& entry : make_zip_range(a, b, c))
   {
      std::cout << std::get<0>(entry) << ", " << std::get<1>(entry) << ", " << std::get<2>(entry) << std::endl;
   }
}
--
Не можешь достичь желаемого — пожелай достигнутого.
Re: C++ идея для стандарта.
От: rean  
Дата: 02.03.18 11:54
Оценка: +5
deleted
Отредактировано 22.04.2019 9:18 deleted2 . Предыдущая версия .
Re: C++ идея для стандарта.
От: night beast СССР  
Дата: 02.03.18 10:41
Оценка: 1 (1) +3
Здравствуйте, pkl, Вы писали:

pkl>Можно ли это сделать уже щас без вундервафлинга?


можно. получится что-то вроде zip_iterator
Re[5]: C++ идея для стандарта.
От: uzhas Ниоткуда  
Дата: 02.03.18 12:26
Оценка: +4
Здравствуйте, pkl, Вы писали:

pkl>Не понял почему логичнее.


потому что это самая первая ассоциация, когда видишь такой код. похоже на list comprehension: https://en.wikipedia.org/wiki/List_comprehension
Re[2]: C++ идея для стандарта.
От: rean  
Дата: 02.03.18 16:33
Оценка: +2 -1 :)
deleted
Отредактировано 22.04.2019 9:17 deleted2 . Предыдущая версия .
Re[3]: C++ идея для стандарта.
От: rg45 СССР  
Дата: 02.03.18 16:57
Оценка: +3
Здравствуйте, rean, Вы писали:


R>Как раз вундерфалинг и получается: целых 29 строк нечитаемого птичьего языка с кучей особенного синтаксиса, typeinfo и большого количества сущностей.

R>Абсолютный антипаттерн во все времена — делаем охрененно сложно и жрущее процессор, только чтобы влепить что-то в неподходящий для этого оператор языка.
R>Жесть!

Ты так возмущаешься, как-будто я предлагаю этот код писать каждый раз. Во-первых, все что идет до строки №46 уже есть в boost, в каком-то виде. Не нравится boost — пожалуйста, написал один раз и пользуйся, сколько влезет. В этом случае от всего примера только функция main и остается. Основной моей мыслью было то, что не не нужно каждую школьную задачку встраивать в язык.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[2]: C++ идея для стандарта.
От: Михaил  
Дата: 02.03.18 23:54
Оценка: +1 :))
Здравствуйте, rg45, Вы писали:

R>Это делается элементарно и смысла тащить это в стандарт лично я не вижу. Тут уже вспоминали про zip. Еще можно было бы вспомнить некоторые полезности из boost, такие как iterator_range, iterator_facade, iterator_adaptor.


R>Но сейчас я хочу показать, как достаоточно просто эта задача решается средсдтвами самого языка, без использования всего перечисленного:


Когда такое встречается в проекте, который достался в поддержку, и срочно необходимо что-то изменить, очень хочется найти этого любителя вые....ться, и популярно обьяснить ему принцип KISS
Re[4]: C++ идея для стандарта.
От: rean  
Дата: 03.03.18 04:15
Оценка: :)))
deleted
Отредактировано 22.04.2019 9:16 deleted2 . Предыдущая версия . Еще …
Отредактировано 04.03.2018 10:53 deleted2 . Предыдущая версия .
C++ идея для стандарта.
От: pkl  
Дата: 02.03.18 10:35
Оценка: +1 :)
Есть 3 контейнера: a, b, c. Хочу запустить 1 range-цикл по ним всем одновременно:

for( auto i1 : a, auto i2 : b, auto i3 : c) {
    
}

На каждой итерации i1, i2, i3 имеет очередное значение из соответствующего контейнера.
Цикл помирает как только исчерпается самый мелкий контейнер.

Пример:
std::vector<int> a = {1, 2, 3};
std::vector<std::string> b = {"hello", "world", "foo", "bar"};
std::vector<int> c = {9, 8, 7, 6, 5, 4, 3, 2, 1, 0};

// Loop will stop after 3 iterations, because 'a' have minumal size = 3.
for ( auto i1 : a, auto i2 : b, auto i3 : c ) {
    std::cout << i1 << ", " << i2 << ", " << i3 << "\n";
}


Output:
1, hello, 9
2, world, 8
3, foo, 7


Жопа ли это? Я тупой наркоман? Можно ли это сделать уже щас без вундервафлинга?
Отредактировано 02.03.2018 10:39 pkl . Предыдущая версия . Еще …
Отредактировано 02.03.2018 10:36 pkl . Предыдущая версия .
Отредактировано 02.03.2018 10:36 pkl . Предыдущая версия .
Re: C++ идея для стандарта.
От: uzhas Ниоткуда  
Дата: 02.03.18 11:11
Оценка: +2
Здравствуйте, pkl, Вы писали:

pkl>На каждой итерации i1, i2, i3 имеет очередное значение из соответствующего контейнера.

pkl>Цикл помирает как только исчерпается самый мелкий контейнер.

такой пробег обычно делается через zip. на плюсах это многословно можно сделать в бусте
слово zip можно встретить в хаскеле и питоне

расширять синтаксис C++ для zip кажется оверкилом, лучше что-то такое иметь в stl
Re[3]: C++ идея для стандарта.
От: GhostCoders Россия  
Дата: 02.03.18 11:23
Оценка: +2
Здравствуйте, pkl, Вы писали:

GC>>for( auto i1 : a, auto i2 : b, auto i3 : c) {

pkl>Не логично. У вложенных другая семантега.
Имею в виду, что для синтаксиса выше логичнее использовать вложенную семантику, а не zip.
Третий Рим должен пасть!
Re: C++ идея для стандарта.
От: Constructor  
Дата: 02.03.18 19:41
Оценка: 27 (1)
Здравствуйте, pkl, Вы писали:

pkl>Есть 3 контейнера: a, b, c. Хочу запустить 1 range-цикл по ним всем одновременно:


pkl>
pkl>for( auto i1 : a, auto i2 : b, auto i3 : c) {
    
pkl>}
pkl>

pkl>На каждой итерации i1, i2, i3 имеет очередное значение из соответствующего контейнера.

pkl>Можно ли это сделать уже щас без вундервафлинга?


Если размеры контейнеров одинаковы, то можно использовать boost::combine:

#include <boost/range/combine.hpp>

// ...

std::vector<int> vector{2, 3, 5};
const std::list<double> list{2.7, 3.14, 1.618};

std::cout << std::right << std::fixed << std::setprecision(3);
std::cout << "Zipped elements:" << std::endl;
for (const auto& elements_tuple : boost::combine(vector, list))
{
    int i;
    double r;
    
    boost::tie(i, r) = elements_tuple;
    std::cout << '(' << std::setw(1) << i << ',' << std::setw(6) << r  << ')' << std::endl;
}


Устранить многословность объявления переменных-элементов контейнера можно, дополнительно задействовав BOOST_FOREACH.
Re[2]: C++ идея для стандарта.
От: Constructor  
Дата: 16.04.18 06:52
Оценка: 10 (1)
Здравствуйте, rg45, Вы писали:

R>Это делается элементарно и смысла тащить это в стандарт лично я не вижу. Тут уже вспоминали про zip. Еще можно было бы вспомнить некоторые полезности из boost, такие как iterator_range, iterator_facade, iterator_adaptor.


R>Но сейчас я хочу показать, как достаоточно просто эта задача решается средсдтвами самого языка, без использования всего перечисленного:


R>https://ideone.com/HkybcL


Ниже приводится вариант этого кода, исправляющий ряд проблем и написанный с использованием возможностей C++17 (fold expressions, class template argument deduction, structured binding, а также некоторых нововведений стандартной библиотеки вроде std::apply и std::as_const):

#include <array>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <list>
#include <tuple>
#include <type_traits>
#include <utility>
#include <vector>


template <typename Type>
using remove_rvalue_reference_t =
    std::conditional_t<std::is_rvalue_reference<Type>{}, std::remove_reference_t<Type>, Type>;


template <typename... Iterators>
class ZipIterator final
{
public:
    ZipIterator(Iterators... iterators) : iterators_tuple_{std::move(iterators)...}
    {
    }

    auto operator*() const
    {
        return std::apply(
            [](auto&... iterators) { return std::tie(std::as_const(*iterators...)); }, iterators_tuple_);
    }

    auto operator*()
    {
        return std::apply([](auto&... iterators) { return std::tie(*iterators...); }, iterators_tuple_);
    }

    decltype(auto) operator++()
    {
        std::apply([](auto&... iterators) { ((void)++iterators, ...); }, iterators_tuple_);

        return *this;
    }

    decltype(auto) operator--()
    {
        std::apply([](auto&... iterators) { ((void)--iterators, ...); }, iterators_tuple_);

        return *this;
    }

    bool operator==(const ZipIterator& other) const
    {
        return are_equal(*this, other, std::make_index_sequence<sizeof...(Iterators)>{});
    }

    bool operator!=(const ZipIterator& other) const
    {
        return !(*this == other);
    }

private:
    std::tuple<Iterators...> iterators_tuple_;

    template <std::size_t... indices>
    static bool are_equal(
        const ZipIterator& zip_iterator1, const ZipIterator& zip_iterator2, std::index_sequence<indices...>)
    {
        return (
            (std::get<indices>(zip_iterator1.iterators_tuple_)
             == std::get<indices>(zip_iterator2.iterators_tuple_))
            || ...);
    }
};


template <typename... Containers>
class Zip final
{
public:
    template <typename... SomeContainers>
    Zip(SomeContainers&&... containers) : containers_tuple_{std::forward<SomeContainers>(containers)...}
    {
    }

    auto cbegin() const
    {
        return form_zipped_iterator([](auto& container) { return std::cbegin(container); });
    }

    auto begin() const
    {
        return cbegin();
    }

    auto begin()
    {
        return form_zipped_iterator([](auto& container) { return std::begin(container); });
    }

    auto cend() const
    {
        return form_zipped_iterator([](auto& container) { return std::cend(container); });
    }

    auto end() const
    {
        return cend();
    }

    auto end()
    {
        return form_zipped_iterator([](auto& container) { return std::end(container); });
    }

private:
    std::tuple<remove_rvalue_reference_t<Containers>...> containers_tuple_;

    template <typename IteratorFunction>
    auto form_zipped_iterator(IteratorFunction&& iterator_function)
    {
        return std::apply(
            [&iterator_function](auto&... containers) {
                return ZipIterator{iterator_function(containers)...};
            },
            containers_tuple_);
    }
};

template <typename... SomeContainers>
Zip(SomeContainers&&...)->Zip<SomeContainers...>;


struct Foo
{
    ~Foo()
    {
        std::cout << "Foo::~Foo()" << std::endl;
        for (auto& e : v_)
        {
            e = 1;
        }
    }

    std::vector<int> v_;
};


int main()
{
    std::cout << std::right << std::fixed << std::setprecision(3);

    std::list list{2.718, 3.142, 6.283, 1.618};

    std::cout << "Zipped elements:" << std::endl;
    for (const auto [ld, vi] : Zip{list, Foo{{2, 3, 5, 8, 13}}.v_})
    {
        std::cout << "(ld = " << ld << ", vi = " << vi << ')' << std::endl;
    }
}


"Лишних" операций копирования/перемещения такой Zip не осуществляет (кроме как в случае передачи временного объекта, для которого производится перемещение, чтобы продлить время его жизни до конца range based for loop, использующего Zip). Это может быть продемонстрировано с помощью вспомогательного класса Array:

template <typename Element, std::size_t size>
class Array final
{
public:
    Array() = default;

    template <
        typename... Types,
        std::enable_if_t<
            (sizeof...(Types) <= size) && std::is_same<std::common_type_t<Types...>, Element>{},
            int> = 0>
    Array(Types&&... values) : data_{std::forward<Types>(values)...}
    {
        std::cout << "'Array' initializer constructor" << std::endl;
    }

    Array(const Array& array) : data_{array.data_}
    {
        std::cout << "'Array' copy constructor" << std::endl;
    }

    Array(Array&& array) : data_{std::move(array.data_)}
    {
        std::cout << "'Array' move constructor" << std::endl;
    }

    Array& operator=(const Array& array)
    {
        std::cout << "'Array' copy assignment operator" << std::endl;
        data_ = array.data_;

        return *this;
    }

    Array& operator=(Array&& array)
    {
        std::cout << "'Array' move assignment operator" << std::endl;
        data_ = std::move(array.data_);

        return *this;
    }

    ~Array()
    {
        std::cout << "'Array' destructor" << std::endl;
        data_ = {};
    }

    auto cbegin() const
    {
        return data_.cbegin();
    }

    auto begin() const
    {
        return data_.begin();
    }

    auto begin()
    {
        return data_.begin();
    }

    auto cend() const
    {
        return data_.cend();
    }

    auto end() const
    {
        return data_.end();
    }

    auto end()
    {
        return data_.end();
    }

private:
    std::array<Element, size> data_;
};

template <typename... Types>
Array(Types&&...)->Array<std::common_type_t<Types...>, sizeof...(Types)>;
Re: C++ идея для стандарта.
От: Nikе Россия  
Дата: 02.03.18 13:03
Оценка: +1
Здравствуйте, pkl, Вы писали:

pkl>Есть 3 контейнера: a, b, c. Хочу запустить 1 range-цикл по ним всем одновременно:


pkl>
pkl>for( auto i1 : a, auto i2 : b, auto i3 : c) {
    
pkl>}
pkl>

А почему не как-то так:
for ( auto i1, i2, i3 : std::tie( a, b, c ) )
Нужно разобрать угил.
Re[2]: C++ идея для стандарта.
От: night beast СССР  
Дата: 02.03.18 16:08
Оценка: +1
Здравствуйте, rg45, Вы писали:

R>   for (auto&& entry : make_zip_range(a, b, c))
R>   {
R>      std::cout << std::get<0>(entry) << ", " << std::get<1>(entry) << ", " << std::get<2>(entry) << std::endl;
R>   }
R>}


когда структуре бандинг заработает, то наверно и без std::get будет можно.
Re[2]: C++ идея для стандарта.
От: Constructor  
Дата: 02.03.18 16:15
Оценка: +1
Здравствуйте, rg45, Вы писали:

R>Но сейчас я хочу показать, как достаоточно просто эта задача решается средсдтвами самого языка, без использования всего перечисленного:


R>https://ideone.com/HkybcL


Объект, возвращаемый make_zip_range, должен обеспечивать пролонгацию времени жизни временных объектов, переданных на вход make_zip_range, до момента завершения range-based for loop. Иначе может произойти страшное.
Re[4]: C++ идея для стандарта.
От: rean  
Дата: 02.03.18 17:27
Оценка: :)
deleted
Отредактировано 22.04.2019 9:17 deleted2 . Предыдущая версия . Еще …
Отредактировано 02.03.2018 17:31 deleted2 . Предыдущая версия .
Re[6]: C++ идея для стандарта.
От: ezdoctor  
Дата: 02.03.18 18:25
Оценка: -1
Здравствуйте, uzhas, Вы писали:

U>Здравствуйте, rean, Вы писали:


R>>Работает правильно.


U>Прочитай исходное сообщение внимательнее, чтобы понять как оно должно работать


По-моему, этой фразой вы отвечаете на вопрос о том, стоит ли вносить такое изменение в стандарт. Если оно настолько интуитивно непонятно, что нужно читать спеку, то внесение этой фичи в стандарт весьма сомнительно.
Re[3]: C++ идея для стандарта.
От: B0FEE664  
Дата: 02.03.18 23:15
Оценка: +1
Здравствуйте, rean, Вы писали:

pkl>>>Можно ли это сделать уже щас без вундервафлинга?

R>..
R>> using reference = std::tuple<decltype(*std::declval<T>())...>;

R>Как раз вундерфалинг и получается: целых 29 строк нечитаемого птичьего языка с кучей особенного синтаксиса, typeinfo и большого количества сущностей.

И где здесь typeinfo?
И каждый день — без права на ошибку...
Re[5]: C++ идея для стандарта.
От: rg45 СССР  
Дата: 03.03.18 06:37
Оценка: +1
Здравствуйте, rean, Вы писали:

R>rg45, никто не умаляет ваши возможности писать шаблонный код. Они действительно впечатляют. Но все же существует промышленный C++, где люди не соревнуются в своем умении щеголять перед толпой, а создают программы, какие надо поддерживать и развивать. Я когда пришел сюда в форум, если често, просто офигел насколько все запущено с этим, судя по последним темам. А еще когда увидел эту тему про идею для стандарта, так совсем глаза на лоб полезли — потому что такие вот стремления людей к синтаксическому сахару все-же поддерживаются общим «безумием толпы». Придет кто-нибудь сюда и подумает, что C++ — это где-то в облаках, метапрограмирование, последние версии стандарта и прочие небесные технологии. А в реальности приходится возиться совсем с другими вещами.


Я удивляюсь, как тебе удается находить в моих сообщениях смысл, которого там нет, а потом еще и спорить по этому поводу. Еще раз, это был просто мой ответ на вопрос топикстартера: я выразил мнение, что не нужно встраивать в язык возможность, которую без труда можно реализовать в любой прикладной библиотеке. А мой пример — это всего лишь крошечный пруф того, что все это действительно легко делается встроенными средствами языка, даже без каких-либо внешних библиотек. Где ты там увидел, чтоб я предлагал использовать этот код в проекте, для меня остается загадкой
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[5]: C++ идея для стандарта.
От: night beast СССР  
Дата: 03.03.18 07:28
Оценка: +1
Здравствуйте, rean, Вы писали:

R>Лично я понимаю интерес программистов к этим вещам. Все-же гребень технологий, и это уводит от рутины, да и просто интересно с точки зрения мужчины — покорять сложности и доказывать себе и другим что можешь. Но, увы, из ваших текстов складывается впечатление, что то что вы пишите — так и надо делать.


гребнем это было году эдак в 2001.
сейчас это просто средство для упрощения клиентского кода.
если кому то хочется писать на C++ с классами без RAII и прочего, то это не значит что всем остальным этого тоже достаточно.
Re: C++ идея для стандарта.
От: Pzz Россия https://github.com/alexpevzner
Дата: 03.03.18 09:04
Оценка: +1
Здравствуйте, pkl, Вы писали:

pkl>
pkl>for( auto i1 : a, auto i2 : b, auto i3 : c) {
    
pkl>}
pkl>

pkl>На каждой итерации i1, i2, i3 имеет очередное значение из соответствующего контейнера.
pkl>Цикл помирает как только исчерпается самый мелкий контейнер.

Увидев такую запись, интуитивно я бы предположил, что такой цикл переберет все возможные комбинации элементов из 3-х контейнеров, а не будет двигаться параллельно сразу по трем.
Re: C++ идея для стандарта.
От: Kernan Ниоткуда https://rsdn.ru/forum/flame.politics/
Дата: 02.03.18 10:40
Оценка:
Здравствуйте, pkl, Вы писали:

pkl>Жопа ли это? Я тупой наркоман? Можно ли это сделать уже щас без вундервафлинга?

Ты можешь им предложить это лично. Улучшения так себе, если честно и мне кажется это можно решеть придумав класс-обёртку контейнер-контейнеров.
Sic luceat lux!
Re: C++ идея для стандарта.
От: GhostCoders Россия  
Дата: 02.03.18 10:58
Оценка:
Здравствуйте, pkl, Вы писали:

pkl>Есть 3 контейнера: a, b, c. Хочу запустить 1 range-цикл по ним всем одновременно:

Логично было бы сделать как три вложенных цикла

for( auto i1 : a, auto i2 : b, auto i3 : c) {
   
}


развернув в
for(auto i1 : a) {
    for(auto i2 : b) {
        for(auto i3 : c) {
        }
    }
}
Третий Рим должен пасть!
Re[2]: C++ идея для стандарта.
От: pkl  
Дата: 02.03.18 11:15
Оценка:
Здравствуйте, night beast, Вы писали:

NB>Здравствуйте, pkl, Вы писали:


pkl>>Можно ли это сделать уже щас без вундервафлинга?


NB>можно. получится что-то вроде zip_iterator

Это несколько более жопно. Хочется в 1 строку встроенными средствами, не дописывая своих херен.
Отредактировано 02.03.2018 11:34 pkl . Предыдущая версия .
Re[2]: C++ идея для стандарта.
От: pkl  
Дата: 02.03.18 11:15
Оценка:
Здравствуйте, GhostCoders, Вы писали:

GC>Здравствуйте, pkl, Вы писали:


pkl>>Есть 3 контейнера: a, b, c. Хочу запустить 1 range-цикл по ним всем одновременно:

GC>Логично было бы сделать как три вложенных цикла

GC>
GC>for( auto i1 : a, auto i2 : b, auto i3 : c) {
   
GC>}
GC>


GC>развернув в

GC>
GC>for(auto i1 : a) {
GC>    for(auto i2 : b) {
GC>        for(auto i3 : c) {
GC>        }
GC>    }
GC>}
GC>

Не логично. У вложенных другая семантега.
Re[4]: C++ идея для стандарта.
От: pkl  
Дата: 02.03.18 11:34
Оценка:
Здравствуйте, GhostCoders, Вы писали:

GC>Здравствуйте, pkl, Вы писали:


GC>>>for( auto i1 : a, auto i2 : b, auto i3 : c) {

pkl>>Не логично. У вложенных другая семантега.
GC>Имею в виду, что для синтаксиса выше логичнее использовать вложенную семантику, а не zip.
Не понял почему логичнее. Вы сначала бежите по внутреннему, потом делаете шаг по внешнему и заново бежите по внутреннему.
Re[2]: C++ идея для стандарта.
От: Nuzhny Россия https://github.com/Nuzhny007
Дата: 02.03.18 12:08
Оценка:
Здравствуйте, rean, Вы писали:

R>А три итератора и использование обычного while цикла и трех проверок на end() уже не C++? Надо обязательно стандарт менять?


...или 1 индекс.
Re[2]: C++ идея для стандарта.
От: pkl  
Дата: 02.03.18 12:10
Оценка:
Здравствуйте, rean, Вы писали:

pkl>>Жопа ли это? Я тупой наркоман? Можно ли это сделать уже щас без вундервафлинга?


R>А три итератора и использование обычного while цикла и трех проверок на end() уже не C++? Надо обязательно стандарт менять?

Ну поменяли же стандарт, введя range based loops, хотя можно было обойтись итераторами.
Re: C++ идея для стандарта.
От: kov_serg Россия  
Дата: 02.03.18 12:29
Оценка:
Здравствуйте, pkl, Вы писали:

pkl>Жопа ли это? Я тупой наркоман? Можно ли это сделать уже щас без вундервафлинга?


https://stdcpp.ru/proposals
Отредактировано 02.03.2018 12:29 kov_serg . Предыдущая версия .
Re[6]: C++ идея для стандарта.
От: pkl  
Дата: 02.03.18 12:44
Оценка:
Здравствуйте, uzhas, Вы писали:

U>Здравствуйте, pkl, Вы писали:


pkl>>Не понял почему логичнее.


U>потому что это самая первая ассоциация, когда видишь такой код. похоже на list comprehension: https://en.wikipedia.org/wiki/List_comprehension

У чувака код работает не так: он много раз бегает по 3, меньше раз бегает по 2 и один раз бегает по 1.
Это совсем не то, что делал мой код из первого поста.
Re[7]: C++ идея для стандарта.
От: uzhas Ниоткуда  
Дата: 02.03.18 12:56
Оценка:
Здравствуйте, pkl, Вы писали:

pkl>У чувака код работает не так


давай ты зажмуришь глаза, сделаешь глубокий вдох и выдох, а потом перечитаешь ветку и попробуешь понять, что тебе пишут
ок?
Re[2]: C++ идея для стандарта.
От: so5team https://stiffstream.com
Дата: 02.03.18 13:07
Оценка:
Здравствуйте, Nikе, Вы писали:

N>А почему не как-то так:

N>for ( auto i1, i2, i3 : std::tie( a, b, c ) )

Легко перепутать со structured binding из C++17:
auto [i1, i2, i3] = std::tie(a, b, c);

?
Re[2]: C++ идея для стандарта.
От: rean  
Дата: 02.03.18 13:35
Оценка:
deleted
Отредактировано 22.04.2019 9:18 deleted2 . Предыдущая версия .
Re[3]: C++ идея для стандарта.
От: uzhas Ниоткуда  
Дата: 02.03.18 13:50
Оценка:
Здравствуйте, rean, Вы писали:

R>Посмотрел, насколько сложно получается. Получается не сложно и вполне читаемо:


у тебя нечитаемо, но это неважно, т.к. работает неправильно
вот так надо: https://ideone.com/ElqIsk
Re[3]: C++ идея для стандарта.
От: TimurSPB Интернет  
Дата: 02.03.18 13:58
Оценка:
pkl>Это несколько более жопно. Хочется в 1 строку встроенными средствами, не дописывая своих херен.
В python это есть из коробки.
Make flame.politics Great Again!
Re[4]: C++ идея для стандарта.
От: rean  
Дата: 02.03.18 13:59
Оценка:
deleted
Отредактировано 22.04.2019 9:17 deleted2 . Предыдущая версия .
Re[5]: C++ идея для стандарта.
От: uzhas Ниоткуда  
Дата: 02.03.18 14:08
Оценка:
Здравствуйте, rean, Вы писали:

R>Работает правильно.


Прочитай исходное сообщение внимательнее, чтобы понять как оно должно работать
Re[3]: C++ идея для стандарта.
От: rg45 СССР  
Дата: 02.03.18 16:25
Оценка:
Здравствуйте, Constructor, Вы писали:

C>Объект, возвращаемый make_zip_range, должен обеспечивать пролонгацию времени жизни временных объектов, переданных на вход make_zip_range, до момента завершения range-based for loop. Иначе может произойти страшное.


Ну это можно. Я открою страшную тайну: в этом эскизе это не единственный дефект
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[3]: C++ идея для стандарта.
От: Ops Россия  
Дата: 02.03.18 16:58
Оценка:
Здравствуйте, Nuzhny, Вы писали:

R>>А три итератора и использование обычного while цикла и трех проверок на end() уже не C++? Надо обязательно стандарт менять?


N>...или 1 индекс.


Индекс не всегда годится, в общем случае надо итераторы.
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.
Re[5]: C++ идея для стандарта.
От: rg45 СССР  
Дата: 02.03.18 17:41
Оценка:
Здравствуйте, rean, Вы писали:

R>Да вообще не надо такое писать. Разве что ради стеба.


Этот пример, на самом деле состоит из двух частей. Первая часть — библиотечная — она пишется один раз, тестируется и спокойно лежит и ждет своего часа. Это как разумная альтернатива тому, чтоб встраивать такую возможность в язык, как это предлагает ТС. И когда она понадобится, мои программы будут получаться вот такими:

   for (auto&& entry : make_zip_range(a, b, c))
   {
      std::cout << std::get<0>(entry) << ", " << std::get<1>(entry) << ", " << std::get<2>(entry) << std::endl;
   }


а твои вот такими: http://rsdn.org/forum/cpp/7069883.1
Автор: rean
Дата: 02.03.18


    auto ia = a.begin();
    auto ib = b.begin();
    auto ic = c.begin();

    for (;;) {
        bool in_a = ia != a.end();
        bool in_b = ib != b.end();
        bool in_c = ic != c.end();
        if (!(in_a || in_b || in_c)) break;

        if (in_a)
            std::cout << *ia;
        else
            std::cout << "-";

        if (in_b)
            std::cout << ", " << (*ib).c_str();
        else
            std::cout << ", -";

        if (in_c)
            std::cout << ", " << *ic;
        else
            std::cout << ", -";

        std::cout << std::endl;

        if (in_a) ++ia;
        if (in_b) ++ib;
        if (in_c) ++ic;
    };


Если тебе твоя программа нравится больше, пожалуйста, я тебе ничего не навязываю. Мне же, извини, это напоминает рецепт какого-то борща.

R>Оно скорей всего у меня даже не откомпилируется на VC++, а boost так это еще + 300 мегабайт в проект.


Спокойно компилируется, можешь проверить.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 02.03.2018 17:48 rg45 . Предыдущая версия . Еще …
Отредактировано 02.03.2018 17:42 rg45 . Предыдущая версия .
Re[3]: C++ идея для стандарта.
От: rg45 СССР  
Дата: 03.03.18 03:35
Оценка:
Здравствуйте, Михaил, Вы писали:

М>Когда такое встречается в проекте, который достался в поддержку, и срочно необходимо что-то изменить, очень хочется найти этого любителя вые....ться, и популярно обьяснить ему принцип KISS


А я где-то предлагал делать такое в проекте? Сколько раз нужно повторить любителям поумничать вот это
Автор: rg45
Дата: 02.03.18
и вот это
Автор: rg45
Дата: 02.03.18
?
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 03.03.2018 8:18 rg45 . Предыдущая версия . Еще …
Отредактировано 03.03.2018 3:47 rg45 . Предыдущая версия .
Отредактировано 03.03.2018 3:43 rg45 . Предыдущая версия .
Re: C++ идея для стандарта.
От: uncommon Ниоткуда  
Дата: 05.03.18 07:16
Оценка:
Здравствуйте, pkl, Вы писали:

pkl>Жопа ли это?


Да

> Я тупой наркоман?


Да

> Можно ли это сделать уже щас без вундервафлинга?


В range-v3, который пытаются стандартизировать, есть zip_view.

https://github.com/ericniebler/range-v3/blob/8ccd974b5cbb91dc9de7ab969abd568fcf569019/include/range/v3/view/zip.hpp
Re: C++ идея для стандарта.
От: MasterZiv СССР  
Дата: 05.03.18 14:19
Оценка:
Здравствуйте, pkl, Вы писали:

pkl>Есть 3 контейнера: a, b, c. Хочу запустить 1 range-цикл по ним всем одновременно:


Слушай, ну очень редкий случай, когда это надо.

А если уж про это что-то хотеть, хотеть надо что-то типа Common Lisp loop facility.
Re: C++ идея для стандарта.
От: Erop Россия  
Дата: 17.04.18 12:36
Оценка:
Здравствуйте, pkl, Вы писали:

pkl>Есть 3 контейнера: a, b, c. Хочу запустить 1 range-цикл по ним всем одновременно:


pkl>
pkl>for( auto i1 : a, auto i2 : b, auto i3 : c) {
    
pkl>}
pkl>


1) IMHO это не надо вообще
2) Если уж кому-то правда надо, то логичнее было бы записывать как-то так:
for( auto [i1, i2, i3] : std::tie( a, b, c ) ) {
}

3) Я не проверял, но есть такое чувство, что если делать на версии языка, которая уже умеет автоматически разбирать кортежи, то для того, что бы заработал синтаксис вроде того, что сверху, достаточно написать шаблонные begin и end для кортежа контейнеров/диапазонов...

Как вариант, можно написать функцию zip, которая возвращает какой-то специальный zip_t, в котором есть кортеж контейнеров и реализация соотв. итератора, и от которого есть функции begin и end

Можно, кстати, ещё и других комбинаторов понаписать.

будет как-то так:
for(auto [ia, ib, ic] : zip( a, b, c ) ) {
    // то, что просил ТС
}

for(auto [ia, ib, ic] : zip( a, zip_optional(b), c ) ) {
    // то, что просил ТС, но ib -- std::optional и конец контейнера b не заканчивает последовательность
}

for(auto [ia, ib, ic] : all_combinations( a, b, c ) ) {
    // то, что не просил ТС
}

// и т. д...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.