Здравствуйте, LaptevVV, Вы писали:
LVV>Кодт, какие "песни и пляски" имеются ввиду? Если formatter объявят const?
А такие, что где-то надо держать кортеж параметров.
Поскольку formatter("xxx") — это r-value (приводимое к const l-value), то
(formatter("xxx") << arg1),
по хорошему, не должен менять состояние форматтера.
Это можно сделать 3 способами:
1) Результат операции — новый объект, хранящий в себе и форматтера, и аргумент. Результат следующей операции — ещё один объект, и так далее.
В принципе, это выгодно с точки зрения расхода памяти и compile-time полиморфизма (все аргументы можно хранить по ссылке — время их жизни равно времени жизни выражения), но структуры данных будут... нетривиальные. Односвязный список с хвоста в начало, либо размещённый в куче список с начала в хвост.
2) Форматтер меняет внутреннее состояние, оставаясь константным внешне.
2.1) У него есть член — указатель на структуру данных, размещённую в куче. Константность объекта формально не навязывает константность агрегату, доступному по указателю/ссылке.
2.2) Эта структура данных является членом, объявленным как mutable. Те же яйца, только в профиль; ну и нет возни с памятью.
Здравствуйте, _nn_, Вы писали:
__>Почему нельзя перегружать этот оператор ?
Потому что сложно компилятору это. Ведь оба последних аргумента должны быть одного типа. Это накладывает некие ограничения на синтаксис декларации этого оператора... Да и не понятно, что им еще делать. Будет надо — перегрузят .
Здравствуйте, Кодт, Вы писали:
К>Здравствуйте, LaptevVV, Вы писали:
LVV>>Кодт, какие "песни и пляски" имеются ввиду? Если formatter объявят const?
К>А такие, что где-то надо держать кортеж параметров. К>Поскольку formatter("xxx") — это r-value (приводимое к const l-value), то К>(formatter("xxx") << arg1), К>по хорошему, не должен менять состояние форматтера. К>Это можно сделать 3 способами:
К>1) Результат операции — новый объект, хранящий в себе и форматтера, и аргумент. Результат следующей операции — ещё один объект, и так далее. К>В принципе, это выгодно с точки зрения расхода памяти и compile-time полиморфизма (все аргументы можно хранить по ссылке — время их жизни равно времени жизни выражения), но структуры данных будут... нетривиальные. Односвязный список с хвоста в начало, либо размещённый в куче список с начала в хвост.
К>2) Форматтер меняет внутреннее состояние, оставаясь константным внешне. К>2.1) У него есть член — указатель на структуру данных, размещённую в куче. Константность объекта формально не навязывает константность агрегату, доступному по указателю/ссылке. К>2.2) Эта структура данных является членом, объявленным как mutable. Те же яйца, только в профиль; ну и нет возни с памятью.
Спасибо!
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Здравствуйте, Larm, Вы писали:
L>Потому что сложно компилятору это. Ведь оба последних аргумента должны быть одного типа. Это накладывает некие ограничения на синтаксис декларации этого оператора... Да и не понятно, что им еще делать. Будет надо — перегрузят .
Это необязательно. Главное, чтобы тип результата был известен
Сложность здесь в другом. Если первый аргумент (селектор) имеет тип, приводимый к bool, то автоматически должен применяться встроенный оператор.
Здравствуйте, Кодт, Вы писали:
К>Сложность здесь в другом. Если первый аргумент (селектор) имеет тип, приводимый к bool, то автоматически должен применяться встроенный оператор.
"obj ? true_part : false_part" мог бы быть равен "obj.operator?: ( true_part, false_part )"
Мне кажется, что из-за необходимости вычисления обоих аргументов для передачи в перегруженный оператор. Это наглядно показывает тот же VB, в iif(cond,true_part,false_part) которого все части вычисляются.
Здравствуйте, Vi2, Вы писали:
Vi2>Здравствуйте, Кодт, Вы писали:
К>>Сложность здесь в другом. Если первый аргумент (селектор) имеет тип, приводимый к bool, то автоматически должен применяться встроенный оператор.
Vi2>
Vi2>"obj ? true_part : false_part" мог бы быть равен "obj.operator?: ( true_part, false_part )"
Vi2>
Vi2>Мне кажется, что из-за необходимости вычисления обоих аргументов для передачи в перегруженный оператор. Это наглядно показывает тот же VB, в iif(cond,true_part,false_part) которого все части вычисляются.
Может перегрузку делать так :
condition ? true_part : false_part;
obj.operator?:(part) // в part будет true_part или false_part в зависимости от условия и ничего не будет вычислятся лишнего.
Единственная проблема с типом возврата...
Может тогда так :
template<typename TRet,typename TPart>
TRet my_class::operator?:(cosnt TPart& part); // для lvaluetemplate<typename TRet,typename TPart>
TRet& my_class::operator?:(cosnt TPart& part); // для rvalue
Здравствуйте, Vi2, Вы писали:
К>>Сложность здесь в другом. Если первый аргумент (селектор) имеет тип, приводимый к bool, то автоматически должен применяться встроенный оператор.
Vi2>
Vi2>"obj ? true_part : false_part" мог бы быть равен "obj.operator?: ( true_part, false_part )"
Vi2>
Да уж объявить-то проблемы не будет.
Vi2>Мне кажется, что из-за необходимости вычисления обоих аргументов для передачи в перегруженный оператор. Это наглядно показывает тот же VB, в iif(cond,true_part,false_part) которого все части вычисляются.
Ну и что, а в перегруженном операторе && тоже обе части выполняются.
Мне кажется, что засада — в том, что перегузка ?: с пользовательским типом, приводимым к bool, даст конфликт...