Size: a a a

2020 October 11

OS

Oleksandr Senkovych in pro.cxx
Ах да, нужно еще без виртуальных функций
источник

OS

Oleksandr Senkovych in pro.cxx
То есть что-то типа
template <typename... Checks>
struct Validator
{
  template <typename... Args>
  bool operator()(Args&& ...args) {
   for_each_type<Checks>([](){ Check()(...); });
   }
}

Не понятно правда что делать с аргументами для каждого Check'a, т.е. как определить какие varargs идут какой проверке.
источник

Е

Егор in pro.cxx
пройдемте в @supapro
источник

ПК

Побитый Кирпич... in pro.cxx
PRoSToC0der
кстати, std::bit_cast все кейсы reinterpret_cast закрывает?
Это для разных целей касты. То что reinterpret_cast юзают неправильно - другой вопрос
источник

ИI

И Ivan in pro.cxx
Oleksandr Senkovych
Поцоны, вопрос по дизайну и архитектуре. У приложения есть большая функция с кучей проверок на то что входящие данные валидны. Проходит какое-то время и нужно написать вторую функцию, которая делает на 90% то же самое что и первая но немного иначе. Проходит еще время - нужно расширить еще в другом месте. Как правильно сделать архитектуру для этого? Вот несколько вариантов которые мне кажутся не оч.
1. Добавить больше аргументов. Мне не нравится потому что много аргументов будут  релевантны только в одном частном случае и бойлерплейтом в других.
2. Разбить на мелкие функции и вместо условного validate(args...) вызывать validateA(aArgs...) && vallidateB(bArgs...) && validateC(cArgs...). Минусом я вижу что если появится нужда для validateD(dArgs...) в будущем то нужно будет его добавлять во множестве разных мест.

может какой-то policy-based здесь подойдет?
Вместо кучи проверок использовать больше осмысленных типов, в которых проверки будут зашиты на уровне конструктора
источник

DS

Dmitry Sokolov in pro.cxx
Oleksandr Senkovych
Поцоны, вопрос по дизайну и архитектуре. У приложения есть большая функция с кучей проверок на то что входящие данные валидны. Проходит какое-то время и нужно написать вторую функцию, которая делает на 90% то же самое что и первая но немного иначе. Проходит еще время - нужно расширить еще в другом месте. Как правильно сделать архитектуру для этого? Вот несколько вариантов которые мне кажутся не оч.
1. Добавить больше аргументов. Мне не нравится потому что много аргументов будут  релевантны только в одном частном случае и бойлерплейтом в других.
2. Разбить на мелкие функции и вместо условного validate(args...) вызывать validateA(aArgs...) && vallidateB(bArgs...) && validateC(cArgs...). Минусом я вижу что если появится нужда для validateD(dArgs...) в будущем то нужно будет его добавлять во множестве разных мест.

может какой-то policy-based здесь подойдет?
Может надо валидировать данные там где они получаются? А в функциях просто ассертить/падать.
источник

OS

Oleksandr Senkovych in pro.cxx
Dmitry Sokolov
Может надо валидировать данные там где они получаются? А в функциях просто ассертить/падать.
Это и есть функция валидации валидации, раньше неё ничего нет
источник

DS

Dmitry Sokolov in pro.cxx
Oleksandr Senkovych
Это и есть функция валидации валидации, раньше неё ничего нет
Непонятно всё. А может не надо писать вторую/третью/пятую функцию? Может сделать класс аргумента таким чтобы в него можно было вносить изменения? И его уже валидировать? Так то можно много чего нафантазировать... А может один параметр от другого зависит etc...
источник

OS

Oleksandr Senkovych in pro.cxx
Dmitry Sokolov
Непонятно всё. А может не надо писать вторую/третью/пятую функцию? Может сделать класс аргумента таким чтобы в него можно было вносить изменения? И его уже валидировать? Так то можно много чего нафантазировать... А может один параметр от другого зависит etc...
Ну мне кажется это ведь типичная ситуация с которой все сталкиваются: есть запросы которые надо провалидировать, логика сложна и может повторятся, копипастить не хочется, а хочется красивый и расширяемый подход.
Класс аргумента можно сделать, не проблема. А что если результат одной проверки является входом другой, хранить его тоже в аргументе?
источник

DS

Dmitry Sokolov in pro.cxx
Oleksandr Senkovych
Ну мне кажется это ведь типичная ситуация с которой все сталкиваются: есть запросы которые надо провалидировать, логика сложна и может повторятся, копипастить не хочется, а хочется красивый и расширяемый подход.
Класс аргумента можно сделать, не проблема. А что если результат одной проверки является входом другой, хранить его тоже в аргументе?
Ну запрос вообще может быть сложной структурой. И не факт что в одном месте можно весь его логически валидировать.
источник
2020 October 12

ПК

Побитый Кирпич... in pro.cxx
Oleksandr Senkovych
Ну мне кажется это ведь типичная ситуация с которой все сталкиваются: есть запросы которые надо провалидировать, логика сложна и может повторятся, копипастить не хочется, а хочется красивый и расширяемый подход.
Класс аргумента можно сделать, не проблема. А что если результат одной проверки является входом другой, хранить его тоже в аргументе?
Без примеров разговор ниочём
источник

ПК

Побитый Кирпич... in pro.cxx
Oleksandr Senkovych
Ну мне кажется это ведь типичная ситуация с которой все сталкиваются: есть запросы которые надо провалидировать, логика сложна и может повторятся, копипастить не хочется, а хочется красивый и расширяемый подход.
Класс аргумента можно сделать, не проблема. А что если результат одной проверки является входом другой, хранить его тоже в аргументе?
> результат одной проверки является входом другой

Это как то странно выглядит. Обычно у validate возврат void или bool хотя бы
источник

G

GoodBye in pro.cxx
[С]
Всем привет, такой вопрос. Есть функция.
void __attribute__((fastcall)) func(const char * restrict inStringTemplate, ...);


Внутри я делаю нечто такое

va_list argptr;
va_start(argptr, inStringTemplate);
uint16_t inStringTemplateLen = strlen(inStringTemplate);
int64_t argCopyIfDigin = 0;
uint8_t argIfDiginLen = 0;
for (void * arg = va_arg(argptr, void *); arg != NULL; arg = va_arg(argptr, void *))
{
   inStringTemplateLen += strlen((char *)arg) - 2;
}
va_start(argptr, inStringTemplate);
char * inString = malloc(inStringTemplateLen + 1);
vsnprintf(inString, inStringTemplateLen + 1, inStringTemplate, argptr);
va_end(argptr);


Но теперь у меня появилась проблема, когда я передаю в фунцию как динамический аргумент не char *, строка
inStringTemplateLen += strlen((char *)arg) - 2;

выкидывает SF.
Я предположил, что могу решить проблему так
if ( !isdigit(arg) )
{
   inStringTemplateLen += strlen((char *)arg) - 2;
}
else
{
   argCopyIfDigin = *((int64_t *)arg);
   argIfDiginLen = 0;
   while ( argCopyIfDigin > 0 )
   {
       argCopyIfDigin /= 10;
       argIfDiginLen++;
   }
   inStringTemplateLen += argIfDiginLen - 2;
}

Но теперь я понял, что не могу просто так взять и понять какой тип находится в
void * arg

Вопрос, как мне такое решить
источник

D

Danya in pro.cxx
GoodBye
[С]
Всем привет, такой вопрос. Есть функция.
void __attribute__((fastcall)) func(const char * restrict inStringTemplate, ...);


Внутри я делаю нечто такое

va_list argptr;
va_start(argptr, inStringTemplate);
uint16_t inStringTemplateLen = strlen(inStringTemplate);
int64_t argCopyIfDigin = 0;
uint8_t argIfDiginLen = 0;
for (void * arg = va_arg(argptr, void *); arg != NULL; arg = va_arg(argptr, void *))
{
   inStringTemplateLen += strlen((char *)arg) - 2;
}
va_start(argptr, inStringTemplate);
char * inString = malloc(inStringTemplateLen + 1);
vsnprintf(inString, inStringTemplateLen + 1, inStringTemplate, argptr);
va_end(argptr);


Но теперь у меня появилась проблема, когда я передаю в фунцию как динамический аргумент не char *, строка
inStringTemplateLen += strlen((char *)arg) - 2;

выкидывает SF.
Я предположил, что могу решить проблему так
if ( !isdigit(arg) )
{
   inStringTemplateLen += strlen((char *)arg) - 2;
}
else
{
   argCopyIfDigin = *((int64_t *)arg);
   argIfDiginLen = 0;
   while ( argCopyIfDigin > 0 )
   {
       argCopyIfDigin /= 10;
       argIfDiginLen++;
   }
   inStringTemplateLen += argIfDiginLen - 2;
}

Но теперь я понял, что не могу просто так взять и понять какой тип находится в
void * arg

Вопрос, как мне такое решить
Думаю в чате по чистому Си помогут охотнее
Его можно найти здесь: @it_chats
источник

IZ

Ilia Zviagin in pro.cxx
GoodBye
[С]
Всем привет, такой вопрос. Есть функция.
void __attribute__((fastcall)) func(const char * restrict inStringTemplate, ...);


Внутри я делаю нечто такое

va_list argptr;
va_start(argptr, inStringTemplate);
uint16_t inStringTemplateLen = strlen(inStringTemplate);
int64_t argCopyIfDigin = 0;
uint8_t argIfDiginLen = 0;
for (void * arg = va_arg(argptr, void *); arg != NULL; arg = va_arg(argptr, void *))
{
   inStringTemplateLen += strlen((char *)arg) - 2;
}
va_start(argptr, inStringTemplate);
char * inString = malloc(inStringTemplateLen + 1);
vsnprintf(inString, inStringTemplateLen + 1, inStringTemplate, argptr);
va_end(argptr);


Но теперь у меня появилась проблема, когда я передаю в фунцию как динамический аргумент не char *, строка
inStringTemplateLen += strlen((char *)arg) - 2;

выкидывает SF.
Я предположил, что могу решить проблему так
if ( !isdigit(arg) )
{
   inStringTemplateLen += strlen((char *)arg) - 2;
}
else
{
   argCopyIfDigin = *((int64_t *)arg);
   argIfDiginLen = 0;
   while ( argCopyIfDigin > 0 )
   {
       argCopyIfDigin /= 10;
       argIfDiginLen++;
   }
   inStringTemplateLen += argIfDiginLen - 2;
}

Но теперь я понял, что не могу просто так взять и понять какой тип находится в
void * arg

Вопрос, как мне такое решить
А ЧТО ты передашь? Не char* , а что?
источник

G

GoodBye in pro.cxx
Ilia Zviagin
А ЧТО ты передашь? Не char* , а что?
inStringTemplate = "Some text %s %d"


Тогда в функцию идет строка и int
источник

IZ

Ilia Zviagin in pro.cxx
GoodBye
[С]
Всем привет, такой вопрос. Есть функция.
void __attribute__((fastcall)) func(const char * restrict inStringTemplate, ...);


Внутри я делаю нечто такое

va_list argptr;
va_start(argptr, inStringTemplate);
uint16_t inStringTemplateLen = strlen(inStringTemplate);
int64_t argCopyIfDigin = 0;
uint8_t argIfDiginLen = 0;
for (void * arg = va_arg(argptr, void *); arg != NULL; arg = va_arg(argptr, void *))
{
   inStringTemplateLen += strlen((char *)arg) - 2;
}
va_start(argptr, inStringTemplate);
char * inString = malloc(inStringTemplateLen + 1);
vsnprintf(inString, inStringTemplateLen + 1, inStringTemplate, argptr);
va_end(argptr);


Но теперь у меня появилась проблема, когда я передаю в фунцию как динамический аргумент не char *, строка
inStringTemplateLen += strlen((char *)arg) - 2;

выкидывает SF.
Я предположил, что могу решить проблему так
if ( !isdigit(arg) )
{
   inStringTemplateLen += strlen((char *)arg) - 2;
}
else
{
   argCopyIfDigin = *((int64_t *)arg);
   argIfDiginLen = 0;
   while ( argCopyIfDigin > 0 )
   {
       argCopyIfDigin /= 10;
       argIfDiginLen++;
   }
   inStringTemplateLen += argIfDiginLen - 2;
}

Но теперь я понял, что не могу просто так взять и понять какой тип находится в
void * arg

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

Вот именно тут:
for (void * arg = va_arg(argptr, void *); arg != NULL; arg = va_arg(argptr, void *))
{
   inStringTemplateLen += strlen((char *)arg) - 2;
}

Что ты ещё хочешь то ?
источник

IZ

Ilia Zviagin in pro.cxx
GoodBye
inStringTemplate = "Some text %s %d"


Тогда в функцию идет строка и int
Вызов твоей функции приведи, покажи
источник

G

GoodBye in pro.cxx
Ilia Zviagin
Так у тебя тут написано явно, что все аргументы твоей функции должны быть строками...

Вот именно тут:
for (void * arg = va_arg(argptr, void *); arg != NULL; arg = va_arg(argptr, void *))
{
   inStringTemplateLen += strlen((char *)arg) - 2;
}

Что ты ещё хочешь то ?
Фунция принимает шаблон строки, N параметров для строки
считает сколько требуется памяти выделить, чтобы заменить в шаблоне теги на значения, выделяю, заменяю и после форматирую ее по своим условиям
источник

IZ

Ilia Zviagin in pro.cxx
GoodBye
Фунция принимает шаблон строки, N параметров для строки
считает сколько требуется памяти выделить, чтобы заменить в шаблоне теги на значения, выделяю, заменяю и после форматирую ее по своим условиям
Нет, твоя функция не может ничего кроме строк принимать
источник