специализация на основании type-traits для operator<<(...)
От: niXman Ниоткуда https://github.com/niXman
Дата: 20.11.13 18:42
Оценка:
приветствую!

нужно перегрузить сабжевый оператор для того, чтоб все выводимые строки оборачивались в "\""

пытаюсь сделать такое:
template<typename T, bool ok = std::is_same<T, std::string>::value /*|| std::is_fundamental<T>::value*/>
std::ostream& operator<< (std::ostream& s, const T &o, typename std::enable_if<ok>::type* = 0) {
    return s << o;
}

на что компилятор мне говорит:

main.cpp:341:94: error: 'std::ostream& std::operator<<(std::ostream&, const T&, typename std::enable_if<ok>::type*)' must take exactly two arguments
std::ostream& operator<< (std::ostream& s, const T &o, typename std::enable_if<ok>::type* = 0) {


вопрос в том, как побороть?

благодарен!
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re: специализация на основании type-traits для operator<<(...)
От: andyp  
Дата: 20.11.13 18:58
Оценка:
Здравствуйте, niXman, Вы писали:

X>приветствую!


X>нужно перегрузить сабжевый оператор для того, чтоб все выводимые строки оборачивались в "\""


X>пытаюсь сделать такое:

X>
X>template<typename T, bool ok = std::is_same<T, std::string>::value /*|| std::is_fundamental<T>::value*/>
X>std::ostream& operator<< (std::ostream& s, const T &o, typename std::enable_if<ok>::type* = 0) {
X>    return s << o;
X>}

X>

X>на что компилятор мне говорит:
X>

X>main.cpp:341:94: error: 'std::ostream& std::operator<<(std::ostream&, const T&, typename std::enable_if<ok>::type*)' must take exactly two arguments
X> std::ostream& operator<< (std::ostream& s, const T &o, typename std::enable_if<ok>::type* = 0) {


X>вопрос в том, как побороть?


X>благодарен!


похоже компилятор намекает, что operator<< может быть только бинарным
Re: специализация на основании type-traits для operator<<(...)
От: niXman Ниоткуда https://github.com/niXman
Дата: 20.11.13 19:01
Оценка:
еще один вопрос по оператору вывода, и, чтоб не создавать еще одну мелкую тему, позвольте мне задать его тут

есть такая функция:
std::ostream& quoting(std::ostream &s, const std::string &o) {
   return s << "\"" << o << "\"";
}

при попытке использовать ее так:
cout << "1:" << quoting("2");

получаю в выводе адрес функции, само собой.
есть ли способ, чтоб использование функции оставить таким как показано, но чтоб не адрес выводился, а квотнутая строка?

спасибо.
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[2]: специализация на основании type-traits для operator<<(...)
От: niXman Ниоткуда https://github.com/niXman
Дата: 20.11.13 19:03
Оценка:
Здравствуйте, andyp, Вы писали:

A>похоже компилятор намекает, что operator<< может быть только бинарным

это я понял. выше же написал об этом.

вопрос в том, каким образом специализировать этот оператор?
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[3]: специализация на основании type-traits для operator<<(...)
От: andyp  
Дата: 20.11.13 19:05
Оценка:
Здравствуйте, niXman, Вы писали:

X>Здравствуйте, andyp, Вы писали:


A>>похоже компилятор намекает, что operator<< может быть только бинарным

X>это я понял. выше же написал об этом.

X>вопрос в том, каким образом специализировать этот оператор?


определи свой класс-враппер EscapedString (ну или еще что-то), хранящий ссылку на std::string и свой operator<< для этого класса. operator<< для std::string уже есть в стандартной библиотеке
Re[4]: специализация на основании type-traits для operator<<(...)
От: niXman Ниоткуда https://github.com/niXman
Дата: 20.11.13 19:09
Оценка:
Здравствуйте, andyp, Вы писали:

A>определи свой класс-враппер EscapedString (ну или еще что-то), хранящий ссылку на std::string и свой operator<< для этого класса. operator<< для std::string уже есть в стандартной библиотеке

так это же весь код придется перелопатить!
я же хотел глобально переопределить.
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[2]: специализация на основании type-traits для operator<<(...)
От: andyp  
Дата: 20.11.13 19:14
Оценка:
Здравствуйте, niXman, Вы писали:

X>еще один вопрос по оператору вывода, и, чтоб не создавать еще одну мелкую тему, позвольте мне задать его тут


X>есть такая функция:

X>
X>std::ostream& quoting(std::ostream &s, const std::string &o) {
X>   return s << "\"" << o << "\"";
X>}
X>

X>при попытке использовать ее так:
X>
X>cout << "1:" << quoting("2");
X>

X>получаю в выводе адрес функции, само собой.
X>есть ли способ, чтоб использование функции оставить таким как показано, но чтоб не адрес выводился, а квотнутая строка?

X>спасибо.




std::string& quoting(const std::string &o) {
     std::ostringstream s;
     s << "\"" << o << "\"";
     return s.str();   
}

???
Re[3]: специализация на основании type-traits для operator<<(...)
От: niXman Ниоткуда https://github.com/niXman
Дата: 20.11.13 19:23
Оценка:
Здравствуйте, andyp, Вы писали:

A>
A>std::string& quoting(const std::string &o) {
A>     std::ostringstream s;
A>     s << "\"" << o << "\"";
A>     return s.str();   
A>}
A>

A>???
нет. так и я могу)
функция описана выше. ее менять не нужно.
думал, что есть какой-то способ...
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[5]: специализация на основании type-traits для operator<<(...)
От: andyp  
Дата: 20.11.13 19:26
Оценка:
Здравствуйте, niXman, Вы писали:

X>Здравствуйте, andyp, Вы писали:


A>>определи свой класс-враппер EscapedString (ну или еще что-то), хранящий ссылку на std::string и свой operator<< для этого класса. operator<< для std::string уже есть в стандартной библиотеке

X>так это же весь код придется перелопатить!
X>я же хотел глобально переопределить.

по идее можно свой operator<<(std::ostream&, std::string) определитьв нужном (например, глобальном) namespace
Re: специализация на основании type-traits для operator<<(...)
От: rg45 СССР  
Дата: 20.11.13 20:02
Оценка: 15 (1) +1
Здравствуйте, niXman, Вы писали:

X>нужно перегрузить сабжевый оператор для того, чтоб все выводимые строки оборачивались в "\""

X>пытаюсь сделать такое:
X>
X>template<typename T, bool ok = std::is_same<T, std::string>::value /*|| std::is_fundamental<T>::value*/>
X>std::ostream& operator<< (std::ostream& s, const T &o, typename std::enable_if<ok>::type* = 0) {
X>    return s << o;
X>}
X>

X>на что компилятор мне говорит:
X>

X>main.cpp:341:94: error: 'std::ostream& std::operator<<(std::ostream&, const T&, typename std::enable_if<ok>::type*)' must take exactly two arguments
X> std::ostream& operator<< (std::ostream& s, const T &o, typename std::enable_if<ok>::type* = 0) {

X>вопрос в том, как побороть?



Тут сразу два соображения.

1. Если уж применять SFINAE, то лучше уж к результату функции в данном случае:
template<typename T, typename U>
using EnableIfString = typename std::enable_if<std::is_same<T, std::string>::value, U>::type;

template<typename T>
EnableIfString<T, std::ostream&> operator<< (std::ostream& s, const T &o) {
   return s << "'" << o << "'";
}


2. SFINAE здесь нафиг не нужен:
std::ostream& operator<< (std::ostream& s, const std::string &o) {
   using std::operator<<; // Без этого уйдем в бесконечную рекурсию
   return s << "'" << o << "'";
}
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[2]: специализация на основании type-traits для operator<<(...)
От: andyp  
Дата: 20.11.13 20:24
Оценка:
Здравствуйте, rg45, Вы писали:

R>Здравствуйте, niXman, Вы писали:


X>>нужно перегрузить сабжевый оператор для того, чтоб все выводимые строки оборачивались в "\""

X>>пытаюсь сделать такое:
X>>
X>>template<typename T, bool ok = std::is_same<T, std::string>::value /*|| std::is_fundamental<T>::value*/>
X>>std::ostream& operator<< (std::ostream& s, const T &o, typename std::enable_if<ok>::type* = 0) {
X>>    return s << o;
X>>}
X>>

X>>на что компилятор мне говорит:
X>>

X>>main.cpp:341:94: error: 'std::ostream& std::operator<<(std::ostream&, const T&, typename std::enable_if<ok>::type*)' must take exactly two arguments
X>> std::ostream& operator<< (std::ostream& s, const T &o, typename std::enable_if<ok>::type* = 0) {

X>>вопрос в том, как побороть?



R>Тут сразу два соображения.


R>1. Если уж применять SFINAE, то лучше уж к результату функции в данном случае:

R>
R>template<typename T, typename U>
R>using EnableIfString = typename std::enable_if<std::is_same<T, std::string>::value, U>::type;

R>template<typename T>
R>EnableIfString<T, std::ostream&> operator<< (std::ostream& s, const T &o) {
R>   return s << "'" << o << "'";
R>}
R>


R>2. SFINAE здесь нафиг не нужен:

R>
R>std::ostream& operator<< (std::ostream& s, const std::string &o) {
R>   using std::operator<<; // Без этого уйдем в бесконечную рекурсию
R>   return s << "'" << o << "'";
R>}
R>


там еще одна проблема будет —

#include <string>
#include <iostream>


std::ostream& operator<<(std::ostream& s , const std::string& ss)
{
    using std::operator<<;
    s<<'A';
    s<<ss;
    s<<'A';
    return s;
}

int main(){
   std::cout<<"1"<<std::endl;
}


будет использовать operator<< из std. Сработает только вот так std::string("1"), а это приведет к изменению кода во многих местах
Re[3]: специализация на основании type-traits для operator<<(...)
От: rg45 СССР  
Дата: 20.11.13 20:32
Оценка: 15 (1) +1
Здравствуйте, andyp, Вы писали:



A>там еще одна проблема будет —

A> . . .
A>будет использовать operator<< из std. Сработает только вот так std::string("1"), а это приведет к изменению кода во многих местах


Да тоже не проблема:

std::ostream& do_output (std::ostream& s, const std::string &o) {
   using std::operator<<;
   return s << "'" << o << "'";
}

std::ostream& operator<< (std::ostream& s, const std::string &o) { return do_output(s, o); }
std::ostream& operator<< (std::ostream& s, const char* o) { return do_output(s, o); }

int main()
{
   std::cout << std::string("Hello") << std::endl;
   std::cout << "Hello" << std::endl;
}
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[4]: специализация на основании type-traits для operator<<(...)
От: andyp  
Дата: 20.11.13 20:41
Оценка:
Здравствуйте, rg45, Вы писали:

R>Здравствуйте, andyp, Вы писали:




A>>там еще одна проблема будет —

A>> . . .
A>>будет использовать operator<< из std. Сработает только вот так std::string("1"), а это приведет к изменению кода во многих местах


R>Да тоже не проблема:


R>
R>std::ostream& do_output (std::ostream& s, const std::string &o) {
R>   using std::operator<<;
R>   return s << "'" << o << "'";
R>}

R>std::ostream& operator<< (std::ostream& s, const std::string &o) { return do_output(s, o); }
R>std::ostream& operator<< (std::ostream& s, const char* o) { return do_output(s, o); }

R>int main()
R>{
R>   std::cout << std::string("Hello") << std::endl;
R>   std::cout << "Hello" << std::endl;
R>}
R>


ну да. пост был для галочки, чтобы nixman про вторую перегрузку не забыл
Re[4]: специализация на основании type-traits для operator<<(...)
От: niXman Ниоткуда https://github.com/niXman
Дата: 20.11.13 21:39
Оценка:
Здравствуйте, rg45, Вы писали:

R>[ccode]

R>std::ostream& do_output (std::ostream& s, const std::string &o) {
R> using std::operator<<;
R> return s << "'" << o << "'";
R>}

что-то я не подумал о таком способе.

спасибо, вопрос закрыт.
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[2]: специализация на основании type-traits для operator<<(...)
От: niXman Ниоткуда https://github.com/niXman
Дата: 21.11.13 07:06
Оценка:
Здравствуйте, niXman, Вы писали:

X>еще один вопрос по оператору вывода, и, чтоб не создавать еще одну мелкую тему, позвольте мне задать его тут


X>есть такая функция:

X>
X>std::ostream& quoting(std::ostream &s, const std::string &o) {
X>   return s << "\"" << o << "\"";
X>}
X>

X>при попытке использовать ее так:
X>
X>cout << "1:" << quoting("2");
X>

X>получаю в выводе адрес функции, само собой.
X>есть ли способ, чтоб использование функции оставить таким как показано, но чтоб не адрес выводился, а квотнутая строка?

а по этому вопросу есть идеи?
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[3]: специализация на основании type-traits для operator<<(...)
От: night beast СССР  
Дата: 21.11.13 07:20
Оценка:
Здравствуйте, niXman, Вы писали:

X>>еще один вопрос по оператору вывода, и, чтоб не создавать еще одну мелкую тему, позвольте мне задать его тут


X>>есть такая функция:

X>>
X>>std::ostream& quoting(std::ostream &s, const std::string &o) {
X>>   return s << "\"" << o << "\"";
X>>}
X>>

X>>при попытке использовать ее так:
X>>
X>>cout << "1:" << quoting("2");
X>>

X>>получаю в выводе адрес функции, само собой.

это странно, потому что я получаю ошибку компиляции при попытке преобразовать "const char *" к "std::ostream"
может ты что-то другое компилируешь?

X>>есть ли способ, чтоб использование функции оставить таким как показано, но чтоб не адрес выводился, а квотнутая строка?


X>а по этому вопросу есть идеи?


можешь сформулировать подробней, чего есть, и чего нужно.
Re[4]: специализация на основании type-traits для operator<<(...)
От: niXman Ниоткуда https://github.com/niXman
Дата: 21.11.13 07:28
Оценка:
да, ошибочка вышла.

вот функция:
std::ostream& quoting(std::ostream &s, const std::string &o) {
   return s << "\"" << o << "\"";
}


а вот так хотелось бы использовать:
cout << "1:" << quoting(cout, "2");
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[5]: специализация на основании type-traits для operator<<(...)
От: night beast СССР  
Дата: 21.11.13 07:36
Оценка:
Здравствуйте, niXman, Вы писали:

X>а вот так хотелось бы использовать:

X>
X>cout << "1:" << quoting(cout, "2");
X>


а что должно выводиться? сейчас печатается адрес std::cout, а нужно?
Re[6]: специализация на основании type-traits для operator<<(...)
От: rg45 СССР  
Дата: 21.11.13 08:52
Оценка: 1 (1)
Здравствуйте, night beast, Вы писали:

X>>а вот так хотелось бы использовать:

X>>
X>>cout << "1:" << quoting(cout, "2");
X>>

NB>а что должно выводиться? сейчас печатается адрес std::cout, а нужно?


Ну при включенной телепатии догадаться можно:

#include <iostream>
#include <string>

template <typename T>
class OutputDecorator
{
public:

   OutputDecorator(const T& object) : m_object(&object) { }

   void operator()(std::ostream& output) const { output << '"' << *m_object << '"'; }

private:
   const T* m_object;
};

template <typename T>
std::ostream& operator << (std::ostream& output, const OutputDecorator<T>& decorator)
{
   decorator(output);
   return output;
}

template <typename T>
OutputDecorator<T> make_decorator(const T& object) { return OutputDecorator<T>(object); }

int main()
{
   std::cout << make_decorator("Hello") << std::endl; // Output: "Hello" (quoted)
}
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[6]: специализация на основании type-traits для operator<<(...)
От: niXman Ниоткуда https://github.com/niXman
Дата: 21.11.13 09:42
Оценка:
Здравствуйте, night beast, Вы писали:

NB>а что должно выводиться? сейчас печатается адрес std::cout, а нужно?

туплю жестко %)

должен выводиться второй аргумент функции, обернутый в двойные кавычки.
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[7]: специализация на основании type-traits для operator<<(...)
От: night beast СССР  
Дата: 21.11.13 09:45
Оценка:
Здравствуйте, niXman, Вы писали:

NB>>а что должно выводиться? сейчас печатается адрес std::cout, а нужно?

X>туплю жестко %)

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


да, можно было догадаться.
у rg45 телепатия сработала как положено
Re[7]: специализация на основании type-traits для operator<<(...)
От: niXman Ниоткуда https://github.com/niXman
Дата: 21.11.13 10:18
Оценка:
Здравствуйте, rg45, Вы писали:

R>
R>#include <iostream>
R>#include <string>

R>template <typename T>
R>class OutputDecorator
R>{
R>public:

R>   OutputDecorator(const T& object) : m_object(&object) { }

R>   void operator()(std::ostream& output) const { output << '"' << *m_object << '"'; }

R>private:
R>   const T* m_object;
R>};

R>template <typename T>
R>std::ostream& operator << (std::ostream& output, const OutputDecorator<T>& decorator)
R>{
R>   decorator(output);
R>   return output;
R>}

R>template <typename T>
R>OutputDecorator<T> make_decorator(const T& object) { return OutputDecorator<T>(object); }

R>int main()
R>{
R>   std::cout << make_decorator("Hello") << std::endl; // Output: "Hello" (quoted)
R>}
R>

а без временного объекта, никак?
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[8]: специализация на основании type-traits для operator<<(...)
От: rg45 СССР  
Дата: 21.11.13 10:46
Оценка:
Здравствуйте, niXman, Вы писали:

X>а без временного объекта, никак?


Ну я пока не вижу, как этого достичь. Потом, этот временный объект ничего не содержит, кроме одного указателя, соответственно и при передаче по значению он не тяжелее указателя.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[9]: специализация на основании type-traits для operator<<(...)
От: niXman Ниоткуда https://github.com/niXman
Дата: 21.11.13 11:07
Оценка:
Здравствуйте, rg45, Вы писали:

R>Потом, этот временный объект ничего не содержит, кроме одного указателя, соответственно и при передаче по значению он не тяжелее указателя.

кстати, вопрос. а почему в нем не используется ссылка? она так вообще, не является сущностью.
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[10]: специализация на основании type-traits для operator<<(...)
От: rg45 СССР  
Дата: 21.11.13 11:19
Оценка: +1
Здравствуйте, niXman, Вы писали:

R>>Потом, этот временный объект ничего не содержит, кроме одного указателя, соответственно и при передаче по значению он не тяжелее указателя.

X>кстати, вопрос. а почему в нем не используется ссылка? она так вообще, не является сущностью.

Очень хороший вопрос. Я не так давно выносил этот вопрос на обсуждение: Non-copy-assignable classes
Автор: rg45
Дата: 04.11.13
. Ссылку использовать можно было бы, но при этом у класса была бы неполноценная (с моей точки зрения) семантика копирования: copy-constructible but not copy-assignable. В данном случае я не вижу каких-либо причин запрещения копирующего присваивания для объектов этого класса, потому и заменил ссылку указателем во внутреннем представлении объека. Конструктор же по-прежнему принимает ссылку, поэтому для внешнего кода эта подмена не заметна, зато мы имеем полноценно копируемые объекты. Это ИМХО, далеко не все разделяют мою точку зрения.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[11]: специализация на основании type-traits для operator<<(...)
От: niXman Ниоткуда https://github.com/niXman
Дата: 21.11.13 14:26
Оценка:
понял.

спасибо, вопрос закрыт.
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[11]: специализация на основании type-traits для operator<<(...)
От: jazzer Россия Skype: enerjazzer
Дата: 21.11.13 15:34
Оценка: 7 (1) +1
Здравствуйте, rg45, Вы писали:

R>Здравствуйте, niXman, Вы писали:


R>>>Потом, этот временный объект ничего не содержит, кроме одного указателя, соответственно и при передаче по значению он не тяжелее указателя.

X>>кстати, вопрос. а почему в нем не используется ссылка? она так вообще, не является сущностью.

R>Очень хороший вопрос. Я не так давно выносил этот вопрос на обсуждение: Non-copy-assignable classes
Автор: rg45
Дата: 04.11.13
. Ссылку использовать можно было бы, но при этом у класса была бы неполноценная (с моей точки зрения) семантика копирования: copy-constructible but not copy-assignable. В данном случае я не вижу каких-либо причин запрещения копирующего присваивания для объектов этого класса, потому и заменил ссылку указателем во внутреннем представлении объека. Конструктор же по-прежнему принимает ссылку, поэтому для внешнего кода эта подмена не заметна, зато мы имеем полноценно копируемые объекты. Это ИМХО, далеко не все разделяют мою точку зрения.


Полноценно копируемым он будет и со ссылкой. Он не будет присваиваемым. И это, имхо, правильно для такой легкой обертки, предназначенной быть временным объектом. Полноценное присваивание, на самом деле, нужно очень редко, в отличие от копирования.

Излишняя гибкость — это тоже не всегда хорошо. Иногда имеет смысл ограничить интерфейс, но сделать при этом его безопасным. Присваивание декоратору, имхо, нафиг не нужно.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[12]: специализация на основании type-traits для operator<<(...)
От: rg45 СССР  
Дата: 21.11.13 15:46
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Излишняя гибкость — это тоже не всегда хорошо. Иногда имеет смысл ограничить интерфейс, но сделать при этом его безопасным. Присваивание декоратору, имхо, нафиг не нужно.


В данном конкретном примере есть какое-нибудь ослабление безопасности от того, что мы не запретили копирующее присваивание или от того, что заменили private ссылку на указатель?
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[13]: специализация на основании type-traits для operator<<(...)
От: jazzer Россия Skype: enerjazzer
Дата: 22.11.13 08:36
Оценка: +2
Здравствуйте, rg45, Вы писали:

R>Здравствуйте, jazzer, Вы писали:


J>>Излишняя гибкость — это тоже не всегда хорошо. Иногда имеет смысл ограничить интерфейс, но сделать при этом его безопасным. Присваивание декоратору, имхо, нафиг не нужно.


R>В данном конкретном примере есть какое-нибудь ослабление безопасности от того, что мы не запретили копирующее присваивание или от того, что заменили private ссылку на указатель?


Наверное, безопасность — это не самое правильное слово здесь. Я имел в виду известный принцип дизайна, которым я лично руководствуюсь больше всего — надо делать компонент легким в правильном использовании и при этом максимально затруднять (а лучше — делать невозможным) его неправильное использование.

В этом смысле ссылка однозначно лучше неконстантного указателя, если не планируется 1) нулевого указателя, 2) переприсваивания.
Потому что, например, очень легко дописать в класс функцию, которая будет этим указателем манипулировать. Со ссылкой это не пройдет, придется поменять ее на указатель сначала, а для этого придется сделать изменения почти в каждой строчке класса.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[14]: специализация на основании type-traits для operator<<(...)
От: rg45 СССР  
Дата: 22.11.13 09:33
Оценка:
Здравствуйте, jazzer, Вы писали:

J>В этом смысле ссылка однозначно лучше неконстантного указателя, если не планируется 1) нулевого указателя, 2) переприсваивания.

J>Потому что, например, очень легко дописать в класс функцию, которая будет этим указателем манипулировать. Со ссылкой это не пройдет, придется поменять ее на указатель сначала, а для этого придется сделать изменения почти в каждой строчке класса.

Вот, "планируется" — здесь ключевое слово (в данном контексте можно рассматривать как синоним слова "проектируется"). Если решение о том, что данный класс не должен быть присваеваемым (изменяемым), является результатом продумывания семантики класса и сценариев его использования — это одно дело, это обдуманное решение и тут я ничего против не имею. Мне же не нравятся случаи, когда запрещение присваивания возникает спонтанно, без каких бы то ни было оснований, просто потому, что "голый" указатель производит эффект красной тряпки.

Каждый класс — это своего рода контракт между Заказчиком и Исполнителем. И если смотреть на вопрос со стороны Заказчика, ему гораздо проще понять и использовать класс, подпадающий под стереотип "класс-значение". Случай, когда класс является copy-constructible, но не copy-assignable так или иначе заставит Заказчика напрячься: "А чем, собственно, вызвано данное ограничение?". На что мы ему можем ответить только лишь: "А потому, что у нас такая реализация". На что у Заказчика появляется резонный вопрос: "Каковы риски и каковы затраты на устранение этого ограничения?". Как честные разработчики мы вынуждены будем ответить: "Риски — ноль, затраты — ноль". Как думаете, что скажет на это Заказчик? Очевидно, он скажет: "Ну так снимите это ограничение и не заставляйте меня задумываться о деталях Вашей реализации".
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[15]: специализация на основании type-traits для operator<<(...)
От: jazzer Россия Skype: enerjazzer
Дата: 22.11.13 11:15
Оценка:
Здравствуйте, rg45, Вы писали:

R>Здравствуйте, jazzer, Вы писали:


J>>В этом смысле ссылка однозначно лучше неконстантного указателя, если не планируется 1) нулевого указателя, 2) переприсваивания.

J>>Потому что, например, очень легко дописать в класс функцию, которая будет этим указателем манипулировать. Со ссылкой это не пройдет, придется поменять ее на указатель сначала, а для этого придется сделать изменения почти в каждой строчке класса.

R>Вот, "планируется" — здесь ключевое слово (в данном контексте можно рассматривать как синоним слова "проектируется"). Если решение о том, что данный класс не должен быть присваеваемым (изменяемым), является результатом продумывания семантики класса и сценариев его использования — это одно дело, это обдуманное решение и тут я ничего против не имею. Мне же не нравятся случаи, когда запрещение присваивания возникает спонтанно, без каких бы то ни было оснований, просто потому, что "голый" указатель производит эффект красной тряпки.


Так класс-обертка, как в твоем примере, именно и обладает "одноразовой" семантикой, которой никакие присваивания не нужны (да и копирования тоже, достаточно move).

R>Каждый класс — это своего рода контракт между Заказчиком и Исполнителем. И если смотреть на вопрос со стороны Заказчика, ему гораздо проще понять и использовать класс, подпадающий под стереотип "класс-значение".


Оно, конечно, так, только вот далеко не все классы под этот стереотип подпадают. Это верно только для простых классов-значений, которые все свое несут в себе. Как только класс начинает ссылаться на что-то внешнее — начинаются вопросы и проблемы (например, каким должно быть копирование — глубоким или нет? И если да, то насколько глубоким?). И в таких случаях как раз лучше (для Заказчика) вообще не иметь возможности копировать и присваивать, чем разбираться с неочевидной ссылочной семантикой.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[16]: специализация на основании type-traits для operator<<(...)
От: rg45 СССР  
Дата: 22.11.13 11:30
Оценка:
Здравствуйте, jazzer, Вы писали:

R>>Каждый класс — это своего рода контракт между Заказчиком и Исполнителем. И если смотреть на вопрос со стороны Заказчика, ему гораздо проще понять и использовать класс, подпадающий под стереотип "класс-значение".


J>Оно, конечно, так, только вот далеко не все классы под этот стереотип подпадают. Это верно только для простых классов-значений, которые все свое несут в себе. Как только класс начинает ссылаться на что-то внешнее — начинаются вопросы и проблемы (например, каким должно быть копирование — глубоким или нет? И если да, то насколько глубоким?). И в таких случаях как раз лучше (для Заказчика) вообще не иметь возможности копировать и присваивать, чем разбираться с неочевидной ссылочной семантикой.


Так в том-то и дело, что мы не можем запретить копирование полностью в данном случае (давайте возможность move пока оставим за скобками, реально она вопрос не решает, а умножает на два). И от вопросов и проблем мы Заказчика все равно не избавили, а вместо этого добавили еще один: "почему копию можно только создать, но сделать ее изменяемой нельзя?".
--
Не можешь достичь желаемого — пожелай достигнутого.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.