Няшная / Говнокод #28292 Ссылка на оригинал

0

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  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
  36. 36
  37. 37
  38. 38
  39. 39
  40. 40
  41. 41
  42. 42
  43. 43
  44. 44
  45. 45
  46. 46
  47. 47
  48. 48
  49. 49
  50. 50
  51. 51
  52. 52
  53. 53
  54. 54
  55. 55
  56. 56
  57. 57
  58. 58
  59. 59
  60. 60
  61. 61
  62. 62
  63. 63
  64. 64
  65. 65
  66. 66
  67. 67
  68. 68
  69. 69
  70. 70
  71. 71
  72. 72
  73. 73
  74. 74
  75. 75
  76. 76
  77. 77
  78. 78
  79. 79
  80. 80
  81. 81
  82. 82
  83. 83
  84. 84
  85. 85
  86. 86
  87. 87
  88. 88
  89. 89
  90. 90
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#define NUMARGS(type,...)  (sizeof((type[]){__VA_ARGS__})/sizeof(type))
#define xDEF(type) typedef struct {size_t size; type* arr;  }  xARR(type)
#define xARR(type) jArr_ ## type

#define A(type, ...) (xARR(type)) {NUMARGS(type,__VA_ARGS__), (type[]){__VA_ARGS__}}

#define _FOR(type, item, Arr) type item=Arr.arr[0]; for(size_t I = 0; I < Arr.size; item=Arr.arr[++I] ) 
// MSVC
#define xFOR(type, item, array) do{  _FOR(type, item, array) {
// GCC, Clang
#define FOR(item, array)        do{ __auto_type Arr=array; _FOR(__auto_type, item, Arr) {
    
#define NEXT }} while(0);

#define OfArray(type,arr) (xARR(type)){sizeof(arr)/sizeof(type), arr }

typedef struct {
    char *name;
    int     id;
} Entry;


typedef struct {const char *name;} Str;
typedef struct {int x[2]; } Pair;

xDEF(Entry);
xDEF(Str);
xDEF(Pair);
xDEF(int);

void printEntry(xARR(Entry) entries)
{
    xFOR(Entry, e, entries)
        printf("%s %d \n", e.name, e.id);
    NEXT
}

void printSquares(xARR(int) ints)
{
    FOR(v, ints)
        printf("%d²=%d\n", v,(int) pow(v,2.));
    NEXT
}

int main(void)
{
    xARR(Entry) e = A(Entry, {"one",1}, {"two",2}, {"three",3});
    printEntry(e);
    
    puts("_______________________________________");
    
    // можно передавать в метод непосредственно аргуметом
    printSquares( A(int, 3, 7, 5, 4) );
    puts("_______________________________________");    
    
    int nums[]={4,3,2,1};
    // можно использовать ранее объявленный массив
    printSquares(OfArray(int,nums));
    
    // можно итерироватьcя по ранее объявленному массиву
    FOR(i, OfArray(int, nums))
        printf("%d-",i);
    NEXT
    
    puts("\n_______________________________________");
    
    //вложенные циклы:
    for (int k=1;k<3;k++)
        FOR(i, A(Str, "kakoi", "bagor"))    
            FOR(j, A(int, 1111,2222,3333))
                printf("%d %s %d\n", k, i.name, j);
            NEXT
        NEXT
    
    puts("_______________________________________");
    
    FOR(v, A(Pair, {1,2}, {11,12}, {20,21}))
        printf("%d,%d\n", v.x[0], v.x[1]);
    NEXT
    puts("_______________________________________");    
    //проблема пустого варарга
    FOR(j, A(int))
        printf("%d\n", j);
    NEXT    
    return(0);
}

https://godbolt.org/z/o9Tv9EvGx

Довёл for~each до ума.

Запостил: 3.14159265 3.14159265, (Updated )

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

  • https://gcc.godbolt.org/z/TPa7f4P9j
    Сделал слайсы как в std::span

    //C++ doesnt do bounds checking so do I.
    #define SLICE(count, span, expr)  ({auto ret=span; expr; ret.size=count; ret;})
    #define GET_FIRST(count, span)       SLICE(count, span,)
    #define GET_LAST( count, span)       SLICE(count, span, ret.arr+=ret.size-count)  
    #define GET_SUB(from, count, span)   SLICE(count, span, ret.arr+=from) 
    
    
    void printSquares(SPAN(int) ints)
    {
        FOR(v, ints)
            printf("%d²=%d\n", v,(int) pow(v,2.));
        NEXT
    }
    void first()
    {
        //slice first / last / subspan examples
        
        int nums[]={1,2,3,4,5,6,7,8};
        puts(" take first 3");    
        printSquares( GET_FIRST (3, AsSpan(int,nums) ));
        
        puts("\n take last 2");    
        printSquares( GET_LAST  (2, AsSpan(int,nums)) );
    
        puts("\n subspan: take 4 from 3");    
        printSquares( GET_SUB   (2, 4, AsSpan(int,nums) ) );
        puts("\n");    
    }
    Ответить
      • > 9/10
        В общем вечер пятницы, ночь субботы. Решил ещё поработать напильником.

        Теперь можно мутировать массивspan в цикле.

        //by pointer
            FOR3(v, ints, &)
                *v =  *v + 100;
            NEXT


        Бонусом поддерживается любая функция и каст
        //в принципе в func возможна любая функция, каст, взятие указателя
            // пример каста: автоконверсия типа
            FOR3(f, ints, (float))
                printf("%f, ", f);
            NEXT    
        
        //int even(x){ return x % 2 == 0;}
            FOR3(e, ints, even)
                printf("%d ", e);
            NEXT


        https://godbolt.org/z/anMYvooxn
        Ответить
        • И самое главное: теперь отлавливается что AsSpan и остальные макросы вызываются на массиве. И мы получаем ошибку компилятора, когда пытаемся вызвать его на указателе, где Сишкой неявно произведёна деградация (std::decay)
          void test(int arr[])
          {
              // decay of array. classical beginner mistake. 
              // -Wsizeof-pointer-div can help but novice ignore warnings
              // here compiler will stop with error
              
              // printSquares( AsSpan(int,arr) );    
              puts("\n");    
          }


          В Сишке есть тонкая грань между массивом и указателем, выражается она в том что на одном sizeof работает правильно, а на другом нет. Но я долгое время никак не мог её выразить в ошибку компилятора.

          Да, в гцц есть -Wsizeof-pointer-div. Но это ворнинг, который анскильные нубы игнорят, не читают. Потому хотелось именно жёсткую ошибку. Пока не заглянул в ядро.
          Магия тут в гццизме (не)совместимости типа массива и указателя на его начало
          __builtin_types_compatible_p(typeof(a), typeof(&(a)[0]))
          Ответить
          • >В Сишке есть тонкая грань между массивом и указателем, выражается она в том что на одном sizeof работает правильно, а на другом нет.


            sizeof для указателя совершенно верно работает: он возвращает размер указателя:)
            Ответить
    • Ключевое слово "auto" можно накостылить через typeof() если что.

      #define ASSIGN_AUTO(var_name, value) typeof(value) var_name = value;

      хотя это гну экстеншен, впрочем как и "__auto_type"
      Ответить
      • Да, я уже указал что __auto_type только для GCC/Clang,
        А если это не гнусня, тогда придётся использовать xFOR, где нужно явно указать тип.

        Так работает и в MSVC (я проверил).

        Просто это несколько неэстетично, т.к. его придётся писать джважды для составных макросов.
        xFOR(int, i, OfArray(int, nums))
        Ответить
      • > хотя это гну экстеншен, впрочем как и "__auto_type"

        Правильное замечение.
        typeof предпочтительнее, поскольку он поддерживается в православном tcc
        А __auto_type там нет.

        https://bellard.org/tcc/tcc-doc.html#GNU-C-extensions

        Я лоханулся, потому что не знаю Сишки.
        Ответить
        • __auto_type это костылёчек чтобы типобезопасно макроёбить?
          Ответить
    • в си ауто это ненужное ключслово, говорящее о локальности пременной
      но она и так блин локальна по умолчанию


      в си не нужно auto, потому что там нет шоблонов

      auto завезли не чтобы заменять им char, а чтобы не выписывать значение для ридонли итератора по мапе
      Ответить
  • FOR operator is based on the possibility of confusion over
    the default value semantics of the new range-based for loop, whereas previous
    methods of looping over containers resulted in reference semantics. This was
    8 A. Parsai et al. noted previously by Stephan Lavavej [14]. In his standard proposal, he lists three problems with the most idiomatic-looking range-based for loop, for (auto elem : range), namely:
    – It might not compile - for example, unique ptr3 elements are not copyable.
    This is problematic both for users who won’t understand the resulting com-
    piler errors, and for users writing generic code that’ll happily compile until
    someone instantiates it for movable-only elements.

    – It might misbehave at runtime - for example, elem = val; will modify the
    copy, but not the original element in the range. Additionally, &elem will be
    invalidated after each iteration.

    – It might be inefficient - for example, unnecessarily copying std::string.
    From a mutation testing perspective, the second reason is the main motivation to create a mutation operator. In the case of a range-based for loop that
    modifies the elements of a container in-place, the correct and generic way to
    write it is for (auto&& elem : range). For all cases except for proxy objects
    and move-only ranges, for (auto& elem : range) works as well


    Какие-то &, &&, какие-то конструкторы копирующие, movable.

    В крестах всё так сложно и всё так запутанно
    Сиплюструп прав, а я виноват.

    https://arxiv.org/pdf/2004.04206.pdf
    Ответить
    • Наш дурдом голосует за Страуструпа.
      Страуструп — точно наш кандидат!
      Ответить
  • Остановите его кто-нибудь, он сейчас в Александреску со Степановым превратится, и потом напишет буст для няшной
    Ответить

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

Где здесь C++, guest?!

    А не использовать ли нам bbcode?


    8