BFE>так как читать такое намного проще читать. Однострочники меня не волнуют.
это нормально. Все равно компактней твоего варианта, плюс не вводит лишних имен. Плюс ошибку в имени определит компилятор
E>>Опять же, ты можешь ошибиться и написать f(b, a). А если я напишу f(.b=42, .a=1), то это будет корректно обработано (ну по крайней мере, если применить правила из питона). E>>Далее, функция может иметь аргументы по умолчанию — void f(a = 1, b = 2, c = 3). И ее можно будет вызывать f(.c=4). Твой вариант с константами тут не поможет... BFE>Это хорошие аргументы до тех пор, пока мы не думаем о виртуальных методах.
а что с ними не так? Такая штука есть например в питоне, в нем все методы виртуальные...
E>>Это к вопросу о нужности лямбд. Зачем нужна лямбда из одной строки, когда можно на 5 строках в другом месте файла изобразить повторно используемый функтор? Вроде как и низачем. Однако ж функторы особо не пишут, и вместо find_if фигачат цикл... BFE>Потому, что для чтения кода важна локальность определения. Редко, когда один и тот же функтор используется более одного раза в программе.
Во во. Та же штука с именованными аргументами...
BFE>Ну и вообще, предложенный метод не достаточно радикален. Перепутать f(.a=1, .b=42) и f(.a=42, .b=1) тоже довольно просто.
Тут по крайней мере четко видно, что есть "а", а что есть "b"
Re[5]: А почему нет вызова функций с именованными аргументам
Проблема с этим способом, как и со всеми похожими способами в С++ та, что имя параметра получается привязанным к типу (как ReplaceOnAdd к bool) и засоряет текущий namespace (нельзя в том же namespace определить новый тип ReplaceOnAdd). На самом деле, с помощью дополнительного класса и макро совсем не трудно сделать и такой синтаксис для именованных параметров:
addElement3(1, ReplaceOnAdd = true);
Но проблемы те же самые, что и у typedef bool ReplaceOnAdd.
Re[7]: А почему нет вызова функций с именованными аргументам
PM>>Кстати, сегодня увидел несколько иной способ использовать булевский параметры без enum:
PM>>[ccode] PM>>typedef bool ReplaceOnAdd;
U>Проблема с этим способом, как и со всеми похожими способами в С++ та, что имя параметра получается привязанным к типу (как ReplaceOnAdd к bool) и засоряет текущий namespace (нельзя в том же namespace определить новый тип ReplaceOnAdd).
Да, пространство имён засоряется, согласен, но не думаю что это сильно критично, ReplaceOnAdd довольно уникальное имя на мой взгляд. А так это достаточно практичный способ для тех, кто не может мириться с bool параметрами. И этот способ работает не только для bool: http://fluxible.blogspot.ru/2014/09/a-trivial-way-to-work-around-boolean.html
Re: А почему нет вызова функций с именованными аргументами?
Да чего уж там функции, на шаблоны тоже неплохо бы продолжить. При куче default параметров сахару не хватает, до Alloc, например, минуя Compare в std::set никак не добраться.
Если извратиться, то тоже обойтись можно, взять те же packed_options в boost::intrusive, но вот как нибудь бы попроще...
C точки зрения реализации проблемы наверное те же, что с аргументами функций, можно же, переобъявляя, их переименовать сто раз.
Тогда что именем считать, first viable или может имя из имплементации? Или любое, но контролировать на совместимость?
void foo(int a, int b);
...
void foo(int b, int a) { // ой, у вас ус отклеился...
}
Re[2]: А почему нет вызова функций с именованными аргументами?
Здравствуйте, sokel, Вы писали:
S>Да чего уж там функции, на шаблоны тоже неплохо бы продолжить. При куче default параметров сахару не хватает, до Alloc, например, минуя Compare в std::set никак не добраться.
+1
S>C точки зрения реализации проблемы наверное те же, что с аргументами функций, можно же, переобъявляя, их переименовать сто раз. S>Тогда что именем считать, first viable или может имя из имплементации? Или любое, но контролировать на совместимость?
Если используется такой вызов, то можно контролировать на "одинаковость" в пределах единицы трансляции
Re[5]: А почему нет вызова функций с именованными аргументам
Здравствуйте, enji, Вы писали:
E>>>Опять же, ты можешь ошибиться и написать f(b, a). А если я напишу f(.b=42, .a=1), то это будет корректно обработано (ну по крайней мере, если применить правила из питона). E>>>Далее, функция может иметь аргументы по умолчанию — void f(a = 1, b = 2, c = 3). И ее можно будет вызывать f(.c=4). Твой вариант с константами тут не поможет... BFE>>Это хорошие аргументы до тех пор, пока мы не думаем о виртуальных методах. E>а что с ними не так? Такая штука есть например в питоне, в нем все методы виртуальные...
Смотрите, сейчас можно написать так:
class A
{
public:
virtual void f(int a) {};
};
class B : public A
{
public:
virtual void f(int b) {};
};
какая функция будет вызвана:
A* p = new B;
p->f(.a = 1);
Или вы хотите поломать совместимость кода?
BFE>>Ну и вообще, предложенный метод не достаточно радикален. Перепутать f(.a=1, .b=42) и f(.a=42, .b=1) тоже довольно просто. E>Тут по крайней мере четко видно, что есть "а", а что есть "b"
С суффиксами это тоже видно. И стандарт менять не надо.
И каждый день — без права на ошибку...
Re[6]: А почему нет вызова функций с именованными аргументами?
Здравствуйте, enji, Вы писали:
E>ну и какие тут проблемы? Просто нельзя вызвать f с именоваными параметрами.
согласен, это согласуется с идеей ниже
E>Если у тебя в одной единице f(int a, int b), а в другой — f(int b, int a) — ну попытка вызвать f(.a=1, .b=2) — нарушение ODR. Такое же, как иметь две структуры с одинаковыми именами и разным содержимым.
это не согласуется с идеей ниже
E>Данная штука ведет себя примерно так же, как и параметры по умолчанию — т.е. разворачивается компилятором в обычный вызов функции сразу в месте вызова с той информацией, которая там компилятору доступна.
этот подход мне кажется вполне работоспособным
с другой стороны, ты выше написал про нарушение ODR, что противоречит этой идее. никакого нарушения не должно быть в примере выше, имена параметров не должны быть частью сигнатуры и проблем с экспортированными функциями опять же не будет
для случаев типа
//a.cppvoid f(int a, int b); // определение где-то в другом месте: в другом файле или либеvoid f(int b, int a);
void g()
{
f(.a = 4, .b = 5); //line (1)
}
надо просто отрубать возможность использования именованных аргументов (не компилировать такой код в строке (1) )
для дефолтных значений параметров ведь в стандарте есть несколько предложений для разруливания конфликтов, когда несколько объявлений идут в одной единице трансляции. можно что-то аналогичное прописать и для имен параметров
Re[6]: А почему нет вызова функций с именованными аргументам
Данная штука ведет себя примерно так же, как и параметры по умолчанию — т.е. разворачивается компилятором в обычный вызов функции сразу в месте вызова с той информацией, которая там компилятору доступна.
, то все очень просто : вызвается метод f из класса A, среди его аргументов ищется a. если он не найден, то компиляция ломается, если найден, то подставляется значение 1. в динамике уже вызовется метод f класса B с аргументом b=1.
Re[7]: А почему нет вызова функций с именованными аргументам
Здравствуйте, uzhas, Вы писали:
BFE>>какая функция будет вызвана: BFE>>
A* p = new B;
p->f(.a = 1);
U>если исходить из U>
U>Данная штука ведет себя примерно так же, как и параметры по умолчанию — т.е. разворачивается компилятором в обычный вызов функции сразу в месте вызова с той информацией, которая там компилятору доступна.
U>, то все очень просто : вызвается метод f из класса A, среди его аргументов ищется a. если он не найден, то компиляция ломается, если найден, то подставляется значение 1. в динамике уже вызовется метод f класса B с аргументом b=1.
Т.е. такой вызов :
B* p = new B;
p->f(.a = 1);
"сломается"?
И каждый день — без права на ошибку...
Re[8]: А почему нет вызова функций с именованными аргументам
Здравствуйте, B0FEE664, Вы писали:
BFE>Или вы хотите поломать совместимость кода?
совместимость кода, имхо, означает, что после некоторого нововведения имеющийся код не сломается. Так как сейчас нет именованных аргументов, то вестимо это условие выполняется. Твой случай ничем не отличается от
void f (int a);
void f (int);
void f(int b) { }
f(.b =1);
и решается точно также — компилятор ругается, если такой код встретился в рамках одной единицы трансляции. Если же разные названия в разных единицах трансляции и функция вызывается с именованными аргументами, то получается что-то вроде нарушения odr. Аналогичные нарушения для классов сейчас не диагностируются.
BFE>>>Ну и вообще, предложенный метод не достаточно радикален. Перепутать f(.a=1, .b=42) и f(.a=42, .b=1) тоже довольно просто. E>>Тут по крайней мере четко видно, что есть "а", а что есть "b"
BFE>С суффиксами это тоже видно. И стандарт менять не надо.
а что за суффиксы?
Re[7]: А почему нет вызова функций с именованными аргументами?
Здравствуйте, uzhas, Вы писали:
U>надо просто отрубать возможность использования именованных аргументов (не компилировать такой код в строке (1) ) U>для дефолтных значений параметров ведь в стандарте есть несколько предложений для разруливания конфликтов, когда несколько объявлений идут в одной единице трансляции. можно что-то аналогичное прописать и для имен параметров
дык и я про тоже — нарушение — не само объявление, а попытка вызова
Re[7]: А почему нет вызова функций с именованными аргументам
вот, к примеру, это интуитивно понятно и красиво для С инициализация структуры. Для плюсов же, в Вашем примере, не совсем понятно что Вы хотите сделать и зачем?