Вот интересно у кого глаз наметан и уже много лет с этим возитесь — сколько времени у вас уйдет на то, чтобы распарсить эту абракадабру и понять как, допустим, ее проинициализировать?
Скажем, проинициализировать так — в корне char с значением 'a', а далее везде массивы с 1 элементом.
Re: char *(*(**foo[][8])())[]; - за сколько распарсите?
Здравствуйте, Shmj, Вы писали:
S>Вот интересно у кого глаз наметан и уже много лет с этим возитесь — сколько времени у вас уйдет на то, чтобы распарсить эту абракадабру и понять как, допустим, ее проинициализировать?
array of unspecified size of array [8] of pointer to pointer to function without parameters returning pointer to array of unspecified size of pointer to char
P.S. Если захочется с этим поиграться, то, возможно тебе придется расширять набор специализаций. Думаю, это будет не очень сложно — по образу и подобию.
P.P.S. Ну и что хочется заметить, что сложность объявлений в C/C++ не является открытием и прямо вот в таком виде в промышленном коде никто такие конструкции не употребляет. Благо есть алиасы типов с помощью которых коду можно придать удобочитаемый вид.
Вот такое нехитрое разложение:
using A = char*[];
using F = A*();
using foo = F**[][8];
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, Shmj, Вы писали:
S>char *(*(**foo[][8])())[]; — за сколько распарсите?
Ты если решил-таки заняться самообразованием (что отрадно), то я бы тебе рекомендовал начать вот с этой замечательной книженции, которую я рекомендовал и рекомендую всем, кто не читал:
Здравствуйте, Shmj, Вы писали:
S>Вот интересно у кого глаз наметан и уже много лет с этим возитесь — сколько времени у вас уйдет на то, чтобы распарсить эту абракадабру и понять как, допустим, ее проинициализировать?
Если б мне такое на кодревью вывалили, ну, оно не прошло бы ревью.
Re[3]: char *(*(**foo[][8])())[]; - за сколько распарсите?
R>array of unspecified size of array [8] of pointer to pointer to function without parameters returning pointer to array of unspecified size of pointer to char
R>P.S. Если захочется с этим поиграться, то, возможно тебе придется расширять набор специализаций. Думаю, это будет не очень сложно — по образу и подобию.
И как по подобию будет для "void (X::*)()" http://coliru.stacked-crooked.com/a/97f7fe57e86d98a4
Re[5]: char *(*(**foo[][8])())[]; - за сколько распарсите?
ИМХО, ты напрасно завел отдельную специализацию для указателей на функции-члены. И члены-данные, и члены-функции можно обработать общей специализацией указателя на член. Разница только в том, что в одном случае будет тип-объект, а в другом тип-функция. И первое и второе потом распарсится соответствующими специализациями. Подход с общей специализацией формирует более правильное представление о структуре синтаксиса (это ведь учебное упражнение). Да и писанины меньше — и свободные функции, и функции-члены сводятся к одному общему анализатору.
_>А лямбды можно впихать?
Можно, но с ограничением: без auto в параметрах. Тип возвращаемого значения может быть auto. Можно одним движением охватить и ляибды, и std::function, и пользовательские функционалы.
01. array of unspecified size of array [8] of pointer to pointer to function () returning pointer to array of unspecified size of pointer to char
02. pointer to function (char, pointer to array [8] of pointer to pointer to function () returning pointer to array of unspecified size of pointer to char, int) returning int
03. pointer to function () returning int
04. pointer to member of 'struct A' of type: int
05. function (lvalue refrence to const char, lvalue refrence to double) returning int
06. immutable function (lvalue refrence to const char, lvalue refrence to double) returning int
07. function () returning int
08. immutable function () returning int
09. immutable functional object () returning void
10. immutable functional object (int) returning double
11. functional object (int) returning double
12. functional object (int, lvalue refrence to const std::string, pointer to const char, double) returning double
13. immutable functional object (int, lvalue refrence to const std::string, double, pointer to const char) returning double
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, wander, Вы писали:
R>>И что, даже предположений не возникает, почему не работает?
W>И как всегда нет от ТС ответа. W>Никогда диалога не получается.
Не все сразу — позже вернусь к этому. Пока нет привычной мне IDE под рукой.
Re[4]: char *(*(**foo[][8])())[]; - за сколько распарсите?
Здравствуйте, rg45, Вы писали:
S>>Вставил ваш пример и чего-то не работает: https://ideone.com/k9ZXbI
R>Только сейчас открыл ссылку — это трындец, конечно. R>А ты комментарии читал вокруг или "вставил" первый фрагмент, который попался под руку? R>И что, даже предположений не возникает, почему не работает?
Тогда не глянул, сейчас посмотрел — read_type же требует передачи 1 аргумента. Но не понятно как вам удалось вызывать ее без аргументов.
лучше. Я бы не брал в команду человека, который хейтит, унижает. Вы, может быть, пока выгодно — не раскрываете свою сущность. Но как только что — ожидай подвоха.
Я никогда не унижаю людей — даже если они имеют некие проблемы с интеллектом или что-то сложно им дается. Каждому свое. Просто либо пройду мимо либо покажу верное решение без перехода на личности.
Re[7]: char *(*(**foo[][8])())[]; - за сколько распарсите?
Здравствуйте, reversecode, Вы писали:
R>то есть то что вы пиявка паразит вы за собой не замечаете ? R>и то как вас все откровенное не любят как минимум в теме С++ тоже ? R>я бы таких пиявок паразитов вообще выгонял ото всюду
Что значит паразит? Форум и создан для обсуждения вопросов. Простые вопросы обсуждают на этом же форуме.
Нет возможности ответить — я вас за язык не тяну, можете не отвечать.
Re: char *(*(**foo[][8])())[]; - за сколько распарсите?
Здравствуйте, Shmj, Вы писали:
S>Вот интересно у кого глаз наметан и уже много лет с этим возитесь — сколько времени у вас уйдет на то, чтобы распарсить эту абракадабру и понять как, допустим, ее проинициализировать?
У балтийцев на контру особый нюх: из нагана в лоб контре — ТЮХ!
Абсолютно в любом языке есть способы писать write only код.
И в любом коллективе есть методы так не делать.
Начиная от организационных: пулреквест не пройдёт ревью, коллеги в курилке набьют морду, подставьте ваши варианты.
И кончая литературными: переписать код так, чтобы он стал читаемым.
Смешанный синтаксис типов в Си плохо читается, поэтому надо использовать синонимы типов, записанные, например, в префиксном виде.
Здравствуйте, Shmj, Вы писали:
S>Вот интересно у кого глаз наметан и уже много лет с этим возитесь — сколько времени у вас уйдет на то, чтобы распарсить эту абракадабру и понять как, допустим, ее проинициализировать?
За такое в production code полагается тапком и нахрен на мороз из профессии.
... << RSDN@Home 1.3.110 alpha 5 rev. 62>>
Re: char *(*(**foo[][8])())[]; - за сколько распарсите?
Здравствуйте, Shmj, Вы писали:
S>Скажем, проинициализировать так — в корне char с значением 'a', а далее везде массивы с 1 элементом.
Кстати, это тоже интересно в качестве ребуса то.
"Всемогущий" GPT не осилил:
char* (*(**foo[][8])())[]; // объявление переменной foochar* arr1[] = {"foo", "bar", "baz"}; // пример массива строкchar* arr2[] = {"one", "two", "three", "four"}; // ещё один массив строк
// определение функции, возвращающей указатель на массив строкchar** func() {
return arr1;
}
// инициализация foo с помощью двух элементовchar* (*(*foo[2][8])())[] = {
{&func}, // первый элемент указывает на функцию, возвращающую arr1
{NULL} // второй элемент - нулевой указатель
};
// изменение второго элемента foo, чтобы он указывал на arr2
foo[1][0] = (char* (*(**)())[]) &arr2;
// использование foochar** res = (*foo[0][0])(); // вызов функции, возвращающей arr1
printf("%s\n", res[1]); // печать "bar"
printf("%s\n", (*foo[1][0])[2]); // печать "three"
Вообще возможно ли это как-то инициализировать и вызвать?
Re[2]: char *(*(**foo[][8])())[]; - за сколько распарсите?
Помню в одном проекте у нас супер-умный чувак был, математик нехилый и вообще вундеркинд.
Так вот, у него была шиза — он всё… всё!!! ВСЁ писал через макросы.
То есть его программа выглядела так
int main()
{
MYSUPERMACROS1;
MYSUPERMARCOS2;
MYSUPERMWCROS3;
}
И эти макросы — это не просто однострочные коды — это охренеть какая сложная взаимосвязанная структура вложенных и зависимых других макросов
Не знай нафига он так делал. Чтоб свою незаменимость подчеркнуть и чтоб в его коде хрен кто после не разобрался?
Короче, с тех пор к нечитаемому коду испытываю жесткое отвращение. Это тупо неуважение к коллегам.
Твой код можно оформить гораздо читаемее. И нефиг извращаться.
Re[2]: char *(*(**foo[][8])())[]; - за сколько распарсите?
Здравствуйте, Shmj, Вы писали:
S>"Всемогущий" GPT не осилил: S>Вообще возможно ли это как-то инициализировать и вызвать?
Да что ж вы такие беспомощные
Ну ладно Chat GPT, ей простительно — она маленькая девочка. Но ты-то — лоб здоровый, которому выше уже все разжевали — что не осилил опять?
#include <iostream>
const char* arr1[] = {"foo", "bar", "baz", nullptr}; // пример массива строкconst char* arr2[] = {"one", "two", "three", "four", nullptr}; // ещё один массив строк
// определение функций, возвращающих указатели на массивы строкconst char* (*func1())[] { return &arr1; }
const char* (*func2())[] { return &arr2; }
// определение указателей на функцииconst char* (*(*fptr1)())[] = &func1;
const char* (*(*fptr2)())[] = &func2;
int main()
{
// Инициализация foo - только не "с помощью двух элементов", а так, как это было в оригинальном варианте - массив произвольного размераconst char*(*(**foo[][8])())[] = {
{ &fptr1 }, // первый элемент указывает на функцию, возвращающую arr1
{ &fptr2 }, // второй элемент указывает на функцию, возвращающую arr2
{ &fptr1, &fptr2 }, // третий элемент указывает на две функции
{ &fptr1, &fptr2, &fptr1, &fptr2, &fptr1, &fptr2, &fptr1, &fptr2 }, // четвертый элемент тоже на что-то указывает
{ }, // пятый элемент - пустой (содержит восемь nullptr)
};
// Aнализ и использование foousing String = const char*;
using ArrayOfString = String[];
using Function = ArrayOfString*();
for (Function** (&afpp)[8] : foo)
{
std::cout << "{ ";
for (Function** fpp : afpp)
{
if (fpp)
{
if (Function* fp = *fpp)
{
if (ArrayOfString* asptr = fp())
{
std::cout << "[ ";
for (const String* s = *asptr; *s; ++s)
{
std::cout << *s << ' ';
}
std::cout << "] ";
}
}
}
}
std::cout << "}" << std::endl;
}
}
g++ -std=c++20 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
{ [ foo bar baz ] }
{ [ one two three four ] }
{ [ foo bar baz ] [ one two three four ] }
{ [ foo bar baz ] [ one two three four ] [ foo bar baz ] [ one two three four ] [ foo bar baz ] [ one two three four ] [ foo bar baz ] [ one two three four ] }
{ }
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, Нomunculus, Вы писали:
Н>Помню в одном проекте у нас супер-умный чувак был, математик нехилый и вообще вундеркинд. Н>Так вот, у него была шиза — он всё… всё!!! ВСЁ писал через макросы. Н>То есть его программа выглядела так
Н>int main() Н>{ Н> MYSUPERMACROS1; Н> MYSUPERMARCOS2; Н> MYSUPERMWCROS3; Н>}
Н>И эти макросы — это не просто однострочные коды — это охренеть какая сложная взаимосвязанная структура вложенных и зависимых других макросов
Н>Не знай нафига он так делал. Чтоб свою незаменимость подчеркнуть и чтоб в его коде хрен кто после не разобрался?
О, я тоже так писал когда-то Лет эдак 25 назад. Моя первая версия алгоритма А-звездочка так была написана. Почему на макросах? Ну чтоб не тратить драгоценные такты процессора на выполнение вызовов функций. Было такое мнение, что в потерях в производительности виноваты вызовы функций А еще я фукнцию извлечения квадратного корня писал на ассемблере, примерно в тот же период Я думаю, многие через это проходили. А некоторые так и застряли в том состоянии, судя по тому, что они тут пишут
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[4]: char *(*(**foo[][8])())[]; - за сколько распарсите?
Здравствуйте, rg45, Вы писали:
R>Ну ладно Chat GPT, ей простительно — она маленькая девочка. Но ты-то — лоб здоровый, которому выше уже все разжевали — что не осилил опять?
GTP такие вопросы по идее должны даваться легче, чем человеку. Для меня загадка почему он не справился.
В С++ много неочевидных моментов, связанных с декларированием сложных вещей. К примеру, пока не увидел какая сигнатура у функции, возвращающей указатель на другую функцию — никогда бы сам не догадался.
Этот пример многое раскрывает.
Re[3]: char *(*(**foo[][8])())[]; - за сколько распарсите?
Здравствуйте, Нomunculus, Вы писали:
Н>int main() Н>{ Н> MYSUPERMACROS1; Н> MYSUPERMARCOS2; Н> MYSUPERMWCROS3; Н>}
Н>И эти макросы — это не просто однострочные коды — это охренеть какая сложная взаимосвязанная структура вложенных и зависимых других макросов
Тут вопрос не чтобы так писать. А чтобы если кто-то уже написал, но хотя бы какие-то шансы были разораться в написанном.
Re[4]: char *(*(**foo[][8])())[]; - за сколько распарсите?
S>В С++ много неочевидных моментов, связанных с декларированием сложных вещей. К примеру, пока не увидел какая сигнатура у функции, возвращающей указатель на другую функцию — никогда бы сам не догадался.
using A = char*[];
using F = A*();
using foo = F**[][8];
Если бы ты воспользовался этим подходом, то очень быстро у тебя все разложилось бы по полочкам. Но ты, как обычно, решил, что написанное не стоит твоего внимания. Да?
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[4]: char *(*(**foo[][8])())[]; - за сколько распарсите?
Здравствуйте, Shmj, Вы писали:
S>В С++ много неочевидных моментов, связанных с декларированием сложных вещей. К примеру, пока не увидел какая сигнатура у функции, возвращающей указатель на другую функцию — никогда бы сам не догадался.
На самом деле, ничего особенно сложного нет, нужно знать лишь пару несложных принципов. Первое, что нужно знать — результатом функции не может быть другая функция или массив, но результатом может быть указатель на функцию или массив. Второе, что нужно знать — для того, чтобы объявить указатель на функцию или массив, нужно использовать дополнительные круглые скобки, которыми мы как-бы присоединим символ указателя к имени массива или функции. Без этих дополнтительных круглых скобок символ указателя будет относиться либо к результату функции, либо к элементу массива.
Конструирование сложного объявления проще всего выполнять последовательно, добавляя новые синтаксические элементы непосредственно слева или справа от имени. Например, имеем изначально простое объявление:
Функция, принимающая строку и возвращающая число:
int foo(const char*);
Указатель на функцию, принимающую строку и возвращающую число (используем дополнительные круглые скобки):
int (*foo)(const char*);
Массив указателей на функции принимающие строку, и возвращающие число (добавляем квадратные скобки с размерностью массива сразу справа от имени):
int (*foo[42])(const char*);
Указатель на массив указателей на функции принимающие строку, и возвращающие число (опять используем дополнительные круглые скобки)
int (*(*foo)[42])(const char*);
Функция, принимающая double, возвращающая указатель на массив указателей на функции принимающие строку, и возвращающие число
(просто добавляем справа от имени декларации список формальных параметров в круглых скобках):
int (*(*foo(double))[42])(const char*);
Указатель на функцию, принимающую double, возвращающую указатель на массив указателей на функции принимающие строку, и возвращающие число
int (*(*(*foo)(double))[42])(const char*);
Анализ выполняется в обратном порядке, начиная от имени объявления.
Сложнее всего, когда имя в объявлении опущено и найти его не всегда просто:
using FooPtr = int (*(*(*)(double))[42])(const char*);
Тут уже нужно иметь некоторую сноровку, чтобы быстро находить точку отсчета, от которой следует проводить разбор.
Но на практике таких многоэтажных объявлений лучше вообще избегать, используя using или typedef.
--
Не можешь достичь желаемого — пожелай достигнутого.