jcxz 241 10 мая, 2017 Опубликовано 10 мая, 2017 · Жалоба Имеется функция: char *StrFunc(char const *str) {} Внутри она использует str именно как char const * (только чтение) и потом возвращает например: str+N (N - типа int). Но в качестве вх. аргумента в неё могут передаваться как char * так и char const * - нет проблем, приведение типа делается автоматом. Но хочется, чтобы и возвращаемое значение было того же типа, что и передано: для char * - char *, для char const * - char const *. Чтобы не было необходимости делать: char const *s; ... ; s = (char const *)StrFunc(s); Понятно, что можно объявить inline функцию, в которой сделать приведение к нужному типу. Но тогда, с низким уровнем оптимизации, функция не будет заинлайнена. Или можно перегрузить эту функцию с другим типом аргумента/возвращаемого значения - опят будут две функции, выполняющие одно действие. Может есть более элегантное решение? Как бы так объявить алиас для данной функции с другим типом аргумента/возвращаемого значения? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
scifi 1 10 мая, 2017 Опубликовано 10 мая, 2017 · Жалоба Имеется функция: char *StrFunc(char const *str) {} Внутри она использует str именно как char const * (только чтение) и потом возвращает например: str+N (N - типа int). Функция принимает указатель на const, возвращает указатель по сути на тот же объект, но убирает const. Это нечестно. То есть должно быть 2 функции: char* f1(char* s); const char* f2(const char* s); Причём код внутри одинаковый. Немного жаль, что в языке нет элегантного способа это разрулить. Предложение такое: const char* f2(const char* s); #define f1(s) (char*)f2(s) Проверка типов сохраняется, всё работает. Логично? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 141 10 мая, 2017 Опубликовано 10 мая, 2017 · Жалоба Понятно, что можно объявить inline функцию, в которой сделать приведение к нужному типу. Но тогда, с низким уровнем оптимизации, функция не будет заинлайнена.Не используйте столь низкие уровни оптимизации. Немного жаль, что в языке нет элегантного способа это разрулить.Смотря в каком языке. В плюсах есть, называется перегрузка функций. Можно объявить две функции с одинаковым именем но разными типами параметров. В зависимости от типа передаваемого параметра будет подставлен вызов соответствующей функции. В общем надо переходить на плюсы, даже если писать на них в стиле обычных Сей, просто постепенно добавляя использование все новых и новых плюсовых плюшек. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 241 10 мая, 2017 Опубликовано 10 мая, 2017 · Жалоба Причём код внутри одинаковый. Немного жаль, что в языке нет элегантного способа это разрулить. Я об этом и говорю. Предложение такое: const char* f2(const char* s); #define f1(s) (char*)f2(s) Проверка типов сохраняется, всё работает. Логично? Плохое решение. Две имени (функций) выполняющие одно и то же действие. И придётся каждый раз думать - какое имя подставить. Не используйте столь низкие уровни оптимизации. А как жить тогда? Ведь уже при уровне "Medium" не производится inlining, а при более высоких - отладка практически невозможна. :(( Смотря в каком языке. В плюсах есть, называется перегрузка функций. Это я знаю (см. исходное сообщение). И это ведёт опять к тому-же - или два раза одно и то же тело описывать или вызывать через inline одно общее тело. Вот если-б можно было один раз описать, а для второго списка аргументов использовать что-то типа typedef ;) typedef Func1 Func2; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
novikovfb 19 10 мая, 2017 Опубликовано 10 мая, 2017 · Жалоба Вот если-б можно было один раз описать, а для второго списка аргументов использовать что-то типа typedef ;) typedef Func1 Func2; шаблоны (template) позволяют такие выкрутасы, но ИМХО, это еще более корявая реализация, чем двойное тело функции. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
scifi 1 10 мая, 2017 Опубликовано 10 мая, 2017 · Жалоба Плохое решение. Две имени (функций) выполняющие одно и то же действие. И придётся каждый раз думать - какое имя подставить. Зато типы возвращаемых значений разные. Поэтому вполне логично, что это должно отражаться в имени функции, то есть где-то там будет const. Меня другое волнует - нельзя взять адрес функции, это же макрос. Но это редко нужно. А как жить тогда? Ведь уже при уровне "Medium" не производится inlining, а при более высоких - отладка практически невозможна. :(( Как жить? Жить и не тужить. Можно подумать, от того, что функция не будет заинлайнена, небо упадёт на землю. Это всё вредные предрассудки, избавляйтесь от них. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 241 10 мая, 2017 Опубликовано 10 мая, 2017 · Жалоба Как жить? Жить и не тужить. Тут есть тема (Не)доработки языков программирования, которые хотели ли бы вы наверное надо туда тему перекинуть - пусть обмозгуют, обжуют Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 141 10 мая, 2017 Опубликовано 10 мая, 2017 · Жалоба А как жить тогда? Ведь уже при уровне "Medium" не производится inlining, а при более высоких - отладка практически невозможна. :((Отлаживайтесь в окне дизассемблера. Отладка в этом окне возможна при любом уровне оптимизации. Я делаю именно так. или вызывать через inline одно общее тело.Это лучше. А что, у вашего компилятор нет _Pragma("inline=forced")? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
k155la3 27 10 мая, 2017 Опубликовано 10 мая, 2017 · Жалоба шаблоны (template) позволяют такие выкрутасы, но ИМХО, это еще более корявая реализация, чем двойное тело функции. Шаблон таже двойная (энная) реализация. И ябы не сказал что корявая. По крайней мере для простых применений (какие я пользую) - самое-то. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Шаманъ 1 10 мая, 2017 Опубликовано 10 мая, 2017 · Жалоба Имеется функция: char *StrFunc(char const *str) {} Внутри она использует str именно как char const * (только чтение) и потом возвращает например: str+N (N - типа int). Вариант :): #define func(str) ((str)+N) Это была больше шутка, впрочем иногда вполне годная ;). Самое близкое к описанному Вами поведение даст _Generic (стандарт С1х), как-то так: #define StrFunc(str) _Generic((str), const char*: (const char*)__StrFunc(str), char*: __StrFunc(str)) Т.е. Вашу функцию делаете в виде char* __StrFunc(const char* str), а потом везде вызываете макрос StrFunc. Поведение будет точно такое, как Вы писали: Но хочется, чтобы и возвращаемое значение было того же типа, что и передано: для char * - char *, для char const * - char const *. Чтобы не было необходимости делать: char const *s; ... ; s = (char const *)StrFunc(s); Еще можно сделать макросы с использованием typeof или __auto_type (расширения GCC). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
esaulenka 7 11 мая, 2017 Опубликовано 11 мая, 2017 · Жалоба Что-то не понял, почему нельзя возвращать указатель на константу? Тогда оно "само" приведётся к неконстанте, если потребуется. char const *StrFunc(char const *str) { return str + 5; } int main(void) { const char str1[] = "Hello, world!\n"; char str2[] = "Hello, world!\n"; const char *res1 = StrFunc (str1); char *res2 = StrFunc (str2); printf(res1); printf(res2); return 0; } UPDATE. Чёрт, опять часть варнингов потерялась... warning: initialization discards ‘const’ qualifier from pointer target type [-Wdiscarded-qualifiers] char *res2 = StrFunc (str2); Да-а, беда. Плюсы с перезагрузкой ждут Вас :-) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
demiurg_spb 0 11 мая, 2017 Опубликовано 11 мая, 2017 · Жалоба https://gcc.gnu.org/onlinedocs/gcc-4.4.7/gc...r-Builtins.html __builtin_constant_p Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 241 17 мая, 2017 Опубликовано 17 мая, 2017 · Жалоба Что-то не понял, почему нельзя возвращать указатель на константу? Тогда оно "само" приведётся к неконстанте, если потребуется. ... UPDATE. Чёрт, опять часть варнингов потерялась... Вот именно. Да-а, беда. Плюсы с перезагрузкой ждут Вас :-) Во-первых - перегрузка. И я писал в исходном сообщении, что это нежелательный путь, так как по сути - будут две одинаковые функции. Тогда уж лучше использовать вариант с inline одной из них. __builtin_constant_p У меня IAR :( Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
krux 8 17 мая, 2017 Опубликовано 17 мая, 2017 · Жалоба А вариант с union вам не подойдет ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 241 17 мая, 2017 Опубликовано 17 мая, 2017 · Жалоба А вариант с union вам не подойдет ? Какой? Возвращать union {char *; char const *;}; ? Ну так задача-то была - чтобы при вызове не городить преобразований типов. А тут ещё более громоздкий вызов получается... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться