1. C++ / Говнокод #21132

    −29

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    23. 23
    24. 24
    25. 25
    26. 26
    27. 27
    28. 28
    29. 29
    30. 30
    31. 31
    32. 32
    33. 33
    34. 34
    35. 35
    #include <iostream>
    #include <vector>
    #include <memory>
    using namespace std;
    
    struct i
    {
     virtual void g() = 0;
    };
    
    struct c:i
    {
     virtual void g() {}
    };
    
    struct ic
    {
     virtual void f(const std::vector<std::shared_ptr<i>>& a) = 0;
    };
    
    struct tc:ic
    {
     virtual void f(const std::vector<std::shared_ptr<i>>& a)
    {
      for(auto&& k: a) k->g();
    }
    };
    
    int main() {
        vector<shared_ptr<c>> k;
        tc a;
        a.f(k);
      cout<<"ok"<<endl;
      return 0;
    }

    http://ideone.com/O7sDT4

    Не убирая интерфейсов и виртуальных функций сделайте чтоб компилилось.
    Давно бесит. Крестосоздатели самособой ковариантность или контравариантность в язык не завезли...

    Запостил: LispGovno, 07 Сентября 2016

    Комментарии (107) RSS

    • показать все, что скрыто#вопрос_ребром #крестокостыли #кококомпиляция
      Ответить
    • показать все, что скрытоПоэтому-то я за "PHP" и за "DevelNext".
      Ответить
    • показать все, что скрыто> ковариантность или контравариантность в язык не завезли
      Тогда и слов таких не знали наверное (я вот и сейчас не знаю).
      Ответить
    • показать все, что скрытоА вообще, скастить вектор указателей на потомка в вектор указателей на родителя в общем случае нельзя - нужно создавать новый вектор и заполнять новыми указателями. Из-за множественного наследования указатель на родительский класс и указатель на дочерний класс могут указывать в разные адреса.
      Ответить
      • показать все, что скрытоПоэтому в крестах принято брать не ссылку на контейнер, а джва итератора.
        Ответить
        • показать все, что скрытоНе по этому. Окей, перепиши через джва итератора если осилишь.
          Ответить
          • показать все, что скрытоЧастично и поэтому тоже. Если функция принимает контейнер, то чтобы ей скормить контейнер предков, придётся старый копировать. А если джва итератора — достаточно скормить джва прокси итератора.

            Вообще, в реальном коде, я уверен что было что-то вроде такого: http://coliru.stacked-crooked.com/a/3e0aec08a554a4bf

            Но так как предназначение кода не ясно и теоретически потомок может не хотеть там цикла, сделаем по другому. Так как тут уже shared_ptr и интерфейсы с виртуальными функциями, то на пирфоманс нам насрать.

            Получается так: http://coliru.stacked-crooked.com/a/b1db9770b8f33cc0
            Ответить
            • показать все, что скрытоНу второй способ мне всегда нравился, не считая того что пирформанс ани_рендж чуть похуже.

              А вот первый - плохо. Разбомбил виртуальные функции, тут может и не важно, но где-то может быть важно
              Ответить
    • показать все, что скрыто> Не убирая интерфейсов и виртуальных функций сделайте чтоб компилилось.
      https://ideone.com/55z8Hz
      Ответить
    • показать все, что скрытоfixed. http://ideone.com/BOXKtK

      да, было бы приятно если бы работало. но с другой стороны, у меня мало сочувствия к клепателям пяти-этажных темплейтов и прочего. или как говорили классики: Inside every large problem, there is a small problem trying to get out.
      Ответить
    • показать все, что скрытоРешается один раз написанием array_view<T>, который хавает vector/list/deque/...<T / TSubclass* / shared_ptr<TSubclass> / ... >
      Ответить
      • показать все, что скрыто> array_view
        > хавает vector/list/deque/
        Во-первых, какой это эррей, если хавает список. Во-вторых, все варианты не предусмотришь. Есть, например, еще boost.containers и boost.intrusive, ты в курсе? В-третьих, это не перфомансно.
        Ответить
      • показать все, что скрыто> Решается один раз написанием array_view<T>
        да написан он давно. boost::any_range, но это все в итоге костыли и от отсутствия нормальной поддержки в крестах полиморфизма не спасает
        Ответить
        • показать все, что скрытоКакой багор )))
          Ответить
        • показать все, что скрытоА как надо, расскажи?
          Ответить
        • показать все, что скрытоможет быть в C++25. проблема известная и решений красивых нет. функциональщину в темплейтах они уже сделали. и я не думаю что только на этом остановятся. пишы в https://isocpp.org/std/submit-a-proposal - я сомневаюсь что ты один с этой проблемой. уверен что если на SO запостишь, то тебе там шаблонных клише ответов навалят. что и есть показатель.
          Ответить
          • показать все, что скрыто> уверен что если на SO запостишь, то тебе там шаблонных клише ответов навалят.
            как и всегда делают крестовики: нет в языке, значит оно не нужно. Примерно это меня ждет.

            А так то реализации ко\контр в крестах нет и вменяемую на базе шаблонов сделать проблематично. Генерики бы помогли, но их в кресты никогда не завезут
            Ответить
    • показать все, что скрытоНеосилятор, смотри, как ты обосрался со своим полиморфизмом.
      benchmarking copy vector
      collecting 100 samples, 1 iterations each, in estimated 19.0089 s
      mean: 25.4931 ms, lb 25.1767 ms, ub 25.8502 ms, ci 0.95
      std dev: 1710.98 μs, lb 1521.54 μs, ub 2.13774 ms, ci 0.95
      found 1 outliers among 100 samples (1%)
      variance is severely inflated by outliers
      
      benchmarking any range
      collecting 100 samples, 1 iterations each, in estimated 20.6897 s
      mean: 42.3631 ms, lb 41.9676 ms, ub 42.8015 ms, ci 0.95
      std dev: 2.12763 ms, lb 1906.91 μs, ub 2.40483 ms, ci 0.95
      found 0 outliers among 100 samples (0%)
      variance is moderately inflated by outliers
      Ответить
      • показать все, что скрытоБенчмарк:
        #include <nonius.h++>
        
        #include <memory>
        #include <vector>
        
        #include <boost/range/any_range.hpp>
        #include <boost/range/adaptor/transformed.hpp>
        
        
        struct A {
            unsigned x;
        };
        
        struct B : A {};
        
        using range_t = boost::any_range<std::shared_ptr<A>, boost::single_pass_traversal_tag, std::shared_ptr<A>, std::ptrdiff_t>;
        
        unsigned f1(const range_t &range) {
            unsigned r = 0;
            for (const auto &x: range) {
                r += x->x;
            }
        
            return r;
        }
        
        unsigned f2(const std::vector<std::shared_ptr<A>> &range) {
            unsigned r = 0;
            for (const auto &x: range) {
                r += x->x;
            }
        
            return r;
        }
        
        
        std::vector<std::shared_ptr<B>> random_b_vector(size_t size) {
            std::vector<std::shared_ptr<B>> v(size, nullptr);
        
            for (auto &p: v) {
                p = std::make_shared<B>();
                p->x = rand();
            }
        
            return v;
        }
        
        
        NONIUS_BENCHMARK("copy vector", [](nonius::chronometer meter) {
            std::vector<std::vector<std::shared_ptr<B>>> data(meter.runs());
        
            for (auto &v: data) {
                v = random_b_vector(1000000);
            }
        
            meter.measure([&] (int i) {
                std::vector<std::shared_ptr<A>> v(data[i].begin(), data[i].end());
                return f2(v);
            });
        })
        
        NONIUS_BENCHMARK("any range", [](nonius::chronometer meter) {
            std::vector<std::vector<std::shared_ptr<B>>> data(meter.runs());
        
            for (auto &v: data) {
                v = random_b_vector(1000000);
            }
        
            meter.measure([&] (int i) {
                return f1(data[i] | boost::adaptors::transformed(std::static_pointer_cast<A, B>));
            });
        })
        Ответить
      • показать все, что скрытоКопирование закончилось раньше эни_рендж? неожиданно.
        Ответить
    • показать все, что скрытоТут как раз хорошо смотрится статический полуморфизьм, а именно использование CRTP паттерна.
      http://coliru.stacked-crooked.com/a/f869a306c93fbf56
      Ответить
      • показать все, что скрытоТут проблема в том, что теперь нельзя принимать интерфейс и не знать ничего о конкретном классе. Конкретный класс всегда должен быть виден.

        В добавок нельзя иметь контейнер с указателями на абстрактный интерфейс: каждый "интерфейс" на самом деле свой класс.

        В общем, если архитектуру приложения разрабатывал жабист, то так не покатит.
        Ответить
        • показать все, что скрыто>>Тут проблема в том, что теперь нельзя принимать интерфейс и не знать ничего о конкретном классе. Конкретный класс всегда должен быть виден.

          Да, это так, в точке инстанцирования компилятор должен знать конкретный передаваемый тип. Другое дело, что часто все уже известно на этапе компиляции и виртуальные функции кроме как оверхеда ничего не дадут.

          >> В добавок нельзя иметь контейнер с указателями на абстрактный интерфейс: каждый "интерфейс" на самом деле свой класс.

          Тут вы неправы, вот пример: http://coliru.stacked-crooked.com/a/7bca0150ba91a374
          Объявлен вектор указателей на абстрактный класс, добавляются элементы разных типов, узнаваемые в рун-тайме. Или что-то другое имелось в виду?

          В общем случае да, для абстрактной архитектуры в вакууме не подойдет, но в некоторых случаях очень даже, учитывая перформанс. Из минусов - раздутый бинарник за счет инстанцирования классов для всех возможных входных типов.
          Ответить
          • показать все, что скрыто> Из минусов - раздутый бинарник за счет инстанцирования классов для всех возможных входных типов.
            Еще один минус в том, что это нечитаемая параша.
            Ответить
          • показать все, что скрытоИмелось в виду вектор указателей на ic. Это тоже интерфейс.
            Ответить
            • показать все, что скрытоДа, но универсального годного решения тут не будет. Либо копируем вектор и радуемся гипотетической возможности параллельных абстрактных иерархий по линии tc и с. Либо решаем конкретную задачу в конкретных граничных условиях.
              Ответить
          • показать все, что скрытоКстати, основной недостаток шаблонов - не раздутый бинарник (мегабайты диска сейчас никто не считает), а раздутое время компиляции. Если шаблонные параметры тянуть через все классы, то время компиляции имеет тенденцию здорово расти, а изменения в любом хидере начинают приводить к перекомпиляции половины проекта.
            Ответить
          • показать все, что скрыто> Из минусов - раздутый бинарник за счет инстанцирования классов для всех возможных входных типов.
            из минусов это будет компилятся полчаса на каждый спп фаел
            блин. меня опередили...
            нахуй так жить. лучше сразу вдоль лучше сразу перебраться на другой язык.

            Борми, а что скажешь тут про раст? он как разрулит эту проблему? никак же?
            Ответить
      • показать все, что скрытоЭто какое-то говно, мне кажется.
        Ответить
    • показать все, что скрыто>>Давно бесит. Крестосоздатели самособой ковариантность или контравариантность в язык не завезли...

      Береш код на С# из поста

      http://ideone.com/PNIH9b

      запускаеш тулзу от сюдава https://github.com/ASDAlexander77/cs2cpp и все. Нихрена делать не нада
      Ответить
      • показать все, что скрытоты безумен, чувак
        switch (kind & UnaryOperatorKind.OpMask)
                    {
                        case UnaryOperatorKind.PrefixIncrement:
                        case UnaryOperatorKind.PostfixIncrement:
                        case UnaryOperatorKind.PrefixDecrement:
                        case UnaryOperatorKind.PostfixDecrement:
                        case UnaryOperatorKind.UnaryMinus:
                            return true;
                    }
        Ответить
      • показать все, что скрытоСобрал я cs2cpp с указанием TargetFrameworkVersion v4.5.1. Только пришлось исправить некоторые файлы проектов (там было слишком много ..\..\..\.., где достаточно всего лишь ..).

        Пример из http://ideone.com/PNIH9b сконвертировался лишь с явным приведением типа:
        a.f((IEnumerable<i>)k);
        вместо
        a.f(k);


        При этом компилятор (как родной от фреймворка для C# 5, так и от MSBuild 14.0) спокойно принимает исходник без явного приведения типа.
        Ответить
    • показать все, что скрытоC++ не нужен
      Ответить

    Добавить комментарий