Программирование игр, создание игрового движка, OpenGL, DirectX, физика, форум
GameDev.ru / Программирование / Форум / C++20 vs C11 (3 стр)

C++20 vs C11 (3 стр)

Страницы: 1 2 3 4 5 Следующая »
exchgПостоялецwww4 июня 201815:16#30
entryway
> Самую главную не исправил. Функция всегда возвращает либо AMD либо ATI.
Эт про какой код речь?
DelfigamerПостоялецwww4 июня 201815:24#31
entryway
> > strupr
> Нет такой функции.
Поскольку она не относится к проблеме наличия RAII в языках, я не стал переделывать код на отвязывание от MSVC++ Runtime.

entryway
> Самую главную не исправил. Функция всегда возвращает либо AMD либо ATI и никогда правильно.
Думаешь? Пусть exchg проверяет, это его магия, у меня она даже не запускается.

Правка: 4 июня 2018 15:26

exchgПостоялецwww4 июня 201815:28#32
Delfigamer
> Думаешь? Пусть exchg проверяет, это его магия, у меня она даже не запускается.
Пришлось компилировать, да там была опечатка, даже 2. Но суть в том, что там не
используется множественный возврат и следовательно нет никаких проблем вызвать
free() после strdup() и при этом количество строк такое же.

Т.е. если вот очень нужно выделить память то вот:

#define AS_ENUM(a, b) a,
#define AS_ARRAY(a, b) [a] = b,
#define GPU_MODEL(X)                            \
    X(AMD,    "AMD")                            \
    X(ATI,    "ATI")                            \
    X(INTEL,  "INTEL")                          \
    X(NVIDIA, "NVIDIA")                         \

enum gpu_model {GPU_MODEL(AS_ENUM) UNKNOWN};
const char* gpu_model_str[] = {GPU_MODEL(AS_ARRAY) };

enum gpu_model GetGPU(void)
{
    char* gpu_vendor = strupr(strdup((char*)glGetString(GL_VENDOR)));
    for (u=0; u<UNKNOWN && !strstr(gpu_vendor, gpu_model_str[u]); ++u)
        ;
    free(gpu_vendor);
    return u;
}
Код не проверял, могут быть ошибки. Чисто иллюстрация мысли. И скажи, что это не проще
чем на плюсах.

Правка: 4 июня 2018 16:00

mr.DIMASПостоялецwww4 июня 201816:07#33
exchg
Мне твой код нравится больше чем крестоговно - эффективно и понятно.

Си вообще очень приятный язык.

Правка: 4 июня 2018 16:08

DelfigamerПостоялецwww4 июня 201816:24#34
exchg
> Пришлось компилировать, да там была опечатка, даже 2. Но суть в том, что там
> не используется множественный возврат и следовательно нет никаких проблем вызвать
> free() после strdup() и при этом количество строк такое же.
Ты просто за деревьями леса не видишь.
Ради того, чтобы стянуть все выходы в одну точку, ты перемешал весь остальной код в лапшу.
Давай прочитаем код из моего примера.
enum gpu_model
{
  UNKNOWN = -1,
  INTEL   = 0,
  AMD     = 1,
  ATI     = 2,
  NVIDIA  = 3
};
Что здесь происходит? Мы вводим имена для моделей гпу в зависимости от производителя. Скорее всего, мы будем определять модель и менять поведение в зависимости от того, какая карточка стоит в компьютере.
int GetGPU()
Функция гласит - "получить GPU" и возвращает целое. В ретроспективе, для лучшей документации тип возврата следовало объявить как gpu_model, однако, даже в этом виде мы можем произвести рассуждение - раз функция возвращает не указатель и не хендл - наверно, она возвращает наименование.
{
  char const* vendor_str = glGetString(GL_VENDOR);
О, действительно - она берёт имя производителя у контекста ГЛ. Скорее всего, мы будем выуживать имена строковыми манипуляциями.
  std::vector<char> vendor_buf(vendor_str, vendor_str + strlen(vendor_str) + 1);
Мы копируем строку в локальный буфер. Видимо, дальше пойдут какие-нибудь преобразования.
  strupr(vendor_buf.data());
"string upper" вызывается с одним аргументом и ничего не возвращает. Как такая функция может быть полезной? Только если она изменит переданную строку на месте. Так вот зачем нам временный буфер!
  if(strstr(vendor_buf.data(), "AMD") != NULL) return AMD;
Если в буфере нашли строку "AMD" - значит, наша карточка - AMD. Окей.
  if(strstr(vendor_buf.data(), "ATI") != NULL) return ATI;
  if(strstr(vendor_buf.data(), "NVIDIA") != NULL) return NVIDIA;
  if(strstr(vendor_buf.data(), "INTEL") != NULL) return INTEL;
Аналогично. Окей.
  return UNKNOWN;
Если не нашли соответствия - значит, у нас карта неизвестного производителя.
}
В общем, получается вот что - эта функция берёт описание вендора из контекста ГЛ, по очереди ищет в нём имена, и сообщает перечислением - к какой именно категории относится имеющаяся карточка.
Скорее всего, эта функция используется в местах, где алгоритм выбирается в зависимости от вендора - в виде if(GetGPU() == VENDORNAME) или switch(GetGPU()) {case VENDORNAME:}. Всё понятно!
_

А теперь читаем пример на макросах:

#define AS_ENUM(a, b) a,
"В качестве перечисления - первый параметр"... это как? И что это там дальше, запятая? Что это? Зачем это? Непонятно.

#define AS_ARRAY(a, b) b,
"В качестве массива - второй параметр" - это, наверно, ещё одна деталь того же трюка. Хотя всё ещё не понятно, что это за трюк вообще и что он делает.
#define GPU_MODEL(X)                            \
    X(AMD,    "AMD")                            \
    X(ATI,    "ATI")                            \
    X(INTEL,  "INTEL")                          \
    X(NVIDIA, "NVIDIA")
А здесь перечисляются вендоры GPU. Видимо, в этой программе в зависимости от вендора карточки выбираются разные алгоритмы.
enum gpu_model {GPU_MODEL(AS_ENUM) UNKNOWN};
const char* gpu_model_str[] = {GPU_MODEL(AS_ARRAY) };
...Воу, что только что произошло?
Ах, действительно, это же макросы.
Вот только, какой код этими макросами здесь вообще записан?
*запускает препроцессор у себя в голове*
Хм, вон оно, значит, как. Не уверен, что раскрыл правильно, но суть вроде ясна.
Как я понял, здесь в коде два согласованных списка - с одной стороны, разным вендорам присвоены номера, с другой - в отдельном массиве под соответствующим номером записано имя вендора строкой.
По-видимому, в этой программе вендора будут искать, по очереди сверяя фактическое имя с элементами массива.
enum gpu_model GetGPU(void)
А! А вот и функция, где определяется вендор.
{
    char* gpu_vendor = (char*)glGetString(GL_VENDOR);
Тут мы берём описание вендора из контекста ГЛ. Окей.
    for (u=0; u<UNKNOWN && strstri(gpu_vendor, gpu_model_str[u]); ++u)
        ;
...Ух.
В этом форе столько всего понапихано, что ничего не понятно.
Чтобы разобраться, попробуем его развернуть.
    u = 0;
    while (u<UNKNOWN && strstri(gpu_vendor, gpu_model_str[u]))
    {
        ++u;
    }
Всё равно, какое-то длинное условие. Надо его ещё сильнее развернуть.
    u = 0;
    while (true)
    {
        if (u>=UNKNOWN)
        {
            break;
        }
        if (!strstri(gpu_vendor, gpu_model_str[u]))
        {
            break;
        }
        ++u;
    }
А! Теперь понятно... вот только код неправильный.
Ну, в общем, да, здесь по очереди имя каждого вендора из массива ищется в полученном описании. Вот только условие поставлено неверно.
По идее, должно работать так - если имя очередного кандидата найдено в фактической строке - мы нашли героя и вышли из цикла. Если же герой не нашёлся, а кандидаты закончились - выходим из цикла без кандидата.
Свернём, что ли, по-человечески, да заодно исправим баг:
    for (u=0; u<UNKNOWN; ++u)
    {
        if (strstri(gpu_vendor, gpu_model_str[u]))
        {
            break;
        }
    }
Ну вот, теперь вроде стало понятнее.
    return u;
}
Ну и возвращаем номер найденного имени - который, по построению списков, совпадает с именем вендора в перечислении.
Но, по-моему, вместо выкрутасов с макросами, здесь лучше было бы раскрыть и расписать перечисление с массивом как они есть. Список вендоров не такой уж и большой, а массив строк вряд ли будет использоваться где-то, кроме этой функции.

Правка: 5 июня 2018 7:03

DelfigamerПостоялецwww4 июня 201816:40#35
В общем, моя версия макросомагии выглядела бы так
#define GPU_MODEL_LIST(def) \
    def(AMD,    "AMD"), \
    def(ATI,    "ATI"), \
    def(INTEL,  "INTEL"), \
    def(NVIDIA, "NVIDIA")
#define GPU_MODEL_ENUM_DEF(name, str) GPU_MODEL_ ## name
#define GPU_MODEL_ARRAY_DEF(name, str) /* [GPU_MODEL_ ## name] = */ str
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))

enum gpu_model {
  GPU_MODEL_LIST(GPU_MODEL_ENUM_DEF),
  GPU_MODEL_UNKNOWN };

static const char* gpu_model_str[] = {
  GPU_MODEL_LIST(GPU_MODEL_ARRAY_DEF) };

enum gpu_model GetGPU(void)
{
  char* vendor_str = strupr(strdup((char*)glGetString(GL_VENDOR)));
  enum gpu_model model = GPU_MODEL_UNKNOWN;
  int i;
  for (i = 0; i < ARRAY_SIZE(gpu_model_str); ++i)
  {
    if (strstr(vendor_str, gpu_model_str[i]))
    {
      model = (enum gpu_model)i;
      break;
    }
  }
  free(vendor_str);
  return model;
}
Но зачем заниматься сексом с си, когда можно спокойно написать на крестах и прилепить extern "C"?

Правка: 4 июня 2018 16:42

exchgПостоялецwww4 июня 201816:55#36
Delfigamer
> "В качестве перечисления - первый параметр"... это как? И что это там дальше,
> запятая? Что это? Зачем это? Непонятно.
> ...Воу, что только что произошло?
> Ах, действительно, это же макросы.
> Вот только, какой код этими макросами здесь вообще записан?
> ..Ух.
> В этом форе столько всего понапихано, что ничего не понятно.
Вы прослушали миниатюру - "гуманитарий и код"

Delfigamer
> В общем, моя версия макросомагии выглядела бы так
Сравни ее с моей и объясни зачем? )))

Delfigamer
> Но зачем заниматься сексом с си, когда можно спокойно написать на крестах и
> прилепить extern "C"?
Пиши на крестах, кто тебе мешает? Вот смотря на твое поделие на си становится
понятно почему Си не любят. )))

Кстати верну тебя к теме, тут не стоит вопрос зачем на Си. Тут кто-то спрашивал разве
на Си будет проще, да с учетом того, что нужно обязательно аллокации делать?

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

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

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

Правка: 4 июня 2018 17:35

ZabПостоялецwww4 июня 201816:56#37
Профессиональный программист на каком надо языке - на таком и пишет. В большинстве случаев выбора никакого нет. Работа идет большим коллективом. Не будешь же ты писать не на том, на чем все остальные?
А все эти споры "что лучше", они говорят лишь о том, что спорящие еще только начинают программированию учиться, что язык для них является чем-то ключевым. Да, может быть где-то что-то проще или сложнее выразить. Ну и что? Выразим проще или сложнее, не убьют нас эти сложности.
elviras9tУдалёнwww4 июня 201817:05#38
My Very Own Code Shi& in C++17 (50 Ways to Die when Coding)
// peace example
enum gpu_model : uint32_t { AMD, ATI, INTEL, NVIDIA, UNKNOWN };
const std::array<std::string, 4> gpu_model_str{ { "AMD", "ATI", "INTEL", "NVIDIA" } };

inline auto GetGPU(void) {
    auto gpu_vendor = std::make_optional<std::string_view>((const char *)glGetString(GL_VENDOR));
    auto iterator = std::find_if(gpu_model_str.begin(), gpu_model_str.end(), [&](auto& s) { return gpu_vendor->find(s) != std::string::npos; });
    return gpu_model(std::distance(gpu_model_str.begin(), iterator));
}

Проверено на симуляторе, ибо подключать OpenGL ради одной функции просто лень.
И еще, к сожалению, не получилось сделать constexpr версию.

Правка: 4 июня 2018 17:43

WentПостоялецwww4 июня 201821:00#39
Delfigamer
Не надо втягивать меня в холивар, перекручивая мои утверждения.
Я не говорил, что на С можно лаконично записать все, что можно лаконично записать в С++. Я не говорил, что это можно сделать безопасней. Я говорил, что стандарт языка С проще и однозначней, чем стандарт С++ и это дает ему неоспоримые преимущества в некоторых (довольно узких, должен признать) областях. Понимаете? Ни словом больше. Да, можно взять подмножество С++ и быть увереным, что любой компилятор С++ его поймет одинаково. Но компиляторов С все равно больше, они проще. И если придется иметь дело с какими-то экзотическими платформами, то с С++ можно облажаться.
Odin_KGПостоялецwww4 июня 201821:05#40
elviras9t
> Какой бы вы язык выбрали, если была полная поддержка хотя бы C++20 в Visual Studio 2019 (т.е. VS 16.x)?
Лучше всего использовать всё новое по минимуму. Уж, совместимость при портировании на другую платформу от этого точно только выиграет. По-моему, вы ни за тем гоняетесь. Если, например, вам особо не требуются исключения, так не используйте их вообще. Если не сильно требуется stl и вы запросто расширяете массивы самостоятельно, то забейте на <vector>. Такой подход даст вам куда больше полезного, чем гонка за новыми версиями языка, которые вы даже в деталях не опробуете, так как появится новая версия. В общем, вы не там и не тем местом пытаетесь программировать.
elviras9tУдалёнwww4 июня 201821:17#41
Odin_KG
> Лучше всего использовать всё новое по минимуму. Уж, совместимость при
> портировании на другую платформу от этого точно только выиграет. По-моему, вы
> ни за тем гоняетесь. Если, например, вам особо не требуются исключения, так не
> используйте их вообще. Если не сильно требуется stl и вы запросто расширяете
> массивы самостоятельно, то забейте на <vector>. Такой подход даст вам куда
> больше полезного, чем гонка за новыми версиями языка, которые вы даже в деталях
> не опробуете, так как появится новая версия. В общем, вы не там и не тем местом
> пытаетесь программировать.

Ну я в своем мирке вообще живу жизнью будды по сути, что можно вписать, я пишу...
https://github.com/world8th/vRt/tree/master/include/vRt
Вообще разительное отличие в сторону старины чем новизны, правда сам API и каркас приложения ещё не разработаны/импортированы. Да и вообще чую на месяц-два затянется (за день так и не успел доделать). Надо бы поторапливаться, ибо народ ждёт хлеба и зрелищ, а жизнь будды превращает очередной проект из грандиозной стройки в долгострой.
Кстати, жить становится уже очень теснее, vRt находится в небывалой близости с "DXR", они аж в аналоговые телескопы видят наш проект. И слово "аналоговый" не комплимент нифига, а описание обычной трубы с увеличительными стеклами, даже без USB портов.
И это ещё пол беды, ибо у них есть ещё телескоп, который вполне себе Хаббл.

Правка: 4 июня 2018 21:28

MrShoorУчастникwww4 июня 201821:28#42
Delfigamer
> Ну давай, расскажи про [s]плюсы[/s] преимущества си перед плюсами и недостатки плюсов
> перед си, я внимательно слушаю
Взять к примеру Картонажника. Я например не удивлюсь, если у негу кукушку сорвало после работы с С++.
Поэтому здоровая психика помоему очень важный плюс простого С по сравнению с С++.
return [](){};Участникwww4 июня 201821:47#43
+ java
+ C++
+ C
ArochПостоялецwww4 июня 201822:08#44
return [](){};
в картинке с java не хватает рук торчащих из унитаза.
Delfigamer
> Скорее всего, эта функция используется в местах, где алгоритм выбирается в
> зависимости от вендора - в виде if(GetGPU() == VENDORNAME) или switch(GetGPU())
> {case VENDORNAME:}. Всё понятно!
серьезно? То есть пользователь на ходу втыкает и вынимает видюхи что нужно каждый раз детектить актуальную? /_-
Страницы: 1 2 3 4 5 Следующая »

/ Форум / Программирование игр / Общее

2001—2018 © GameDev.ru — Разработка игр