Перегрузить <<
От: Аноним  
Дата: 07.12.03 12:38
Оценка:
Добрый день!

Как мне перегрузть оператор << в классе, что бы можно было делать так:

class CFoo
{
 ...
 void operator <<(???) {???}
 ...
};
CFoo f;
f << "Число" << 5 ;


Спасибо.
Re: Перегрузить <<
От: Alxndr Германия http://www.google.com/profiles/alexander.poluektov#buzz
Дата: 07.12.03 13:21
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Как мне перегрузть оператор << в классе, что бы можно было делать так:


А>
А>class CFoo
А>{
А> ...
А> CFoo& operator <<(int i) {/* здесь логика перегрузки */}
А> ...
А>};
А>CFoo f;
А>f << "Число" << 5 ;
А>


Исправлено по просьбе автора. -- ПК
Re[2]: Перегрузить <<
От: Аноним  
Дата: 07.12.03 17:39
Оценка:
Здравствуйте, Alxndr, Вы писали:

А>>
А>>class CFoo
А>>{
А>> ...
А>> f& operator <<(int i) {/* здесь логика перегрузки */}
А>> ...
А>>};
А>>CFoo f;
А>>f << "Число" << 5 ;
А>>


Не понял — можешь разъяснить...
Re: Перегрузить <<
От: Шахтер Интернет  
Дата: 07.12.03 18:18
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>Добрый день!


А>Как мне перегрузть оператор << в классе, что бы можно было делать так:


А>
А>class CFoo
А>{
А> ...
А> void operator <<(???) {???}
А> ...
А>};
А>CFoo f;
А>f << "Число" << 5 ;
А>


А>Спасибо.


class CFoo
{
 ...
 CFoo & operator << (int x) { ... return *this; }
 CFoo & operator << (char *x) { ... return *this; }
 CFoo & operator << (const char *x) { ... return *this; }
 ...
};
CFoo f;
f << "Число" << 5 ;
... << RSDN@Home 1.1.0 stable >>
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[2]: Перегрузить <<
От: Павел Кузнецов  
Дата: 07.12.03 18:54
Оценка: +1
Здравствуйте, Шахтер, Вы писали:

Ш>
Ш>class CFoo
Ш>{
Ш> ...
Ш> CFoo & operator << (int x) { ... return *this; }
Ш> CFoo & operator << (char *x) { ... return *this; }
Ш> CFoo & operator << (const char *x) { ... return *this; }
Ш> ...
Ш>};
Ш>


А зачем обе версии: и operator << (char *x), и operator << (const char *x)?
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[3]: Перегрузить <<
От: Шахтер Интернет  
Дата: 07.12.03 19:24
Оценка:
Здравствуйте, Павел Кузнецов, Вы писали:

ПК>Здравствуйте, Шахтер, Вы писали:


Ш>>
Ш>>class CFoo
Ш>>{
Ш>> ...
Ш>> CFoo & operator << (int x) { ... return *this; }
Ш>> CFoo & operator << (char *x) { ... return *this; }
Ш>> CFoo & operator << (const char *x) { ... return *this; }
Ш>> ...
Ш>>};
Ш>>


ПК>А зачем обе версии: и operator << (char *x), и operator << (const char *x)?


Затем, что если ещё добавить

template <class T>
CFoo & operator << (const T &x) { ... return *this; }


то начнутся проблемы.
... << RSDN@Home 1.1.0 stable >>
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[4]: Перегрузить <<
От: Павел Кузнецов  
Дата: 07.12.03 19:46
Оценка:
Здравствуйте, Шахтер, Вы писали:

ПК>>А зачем обе версии: и operator << (char *x), и operator << (const char *x)?


Ш>Затем, что если ещё добавить


Ш>
Ш>template <class T>
Ш>CFoo & operator << (const T &x) { ... return *this; }
Ш>


Ш>то начнутся проблемы.


Хм... Какие?

Например, следующая программа:
#include <iostream>

class CFoo
{
public:
 CFoo & operator << (int x) {
   std::cout << "operator << (int)" << std::endl;
   return *this; }

 CFoo & operator << (const char *x)  {
   std::cout << "operator << (const char *)" << std::endl;
   return *this; }

 template<class T>
 CFoo & operator << (const T&) {
   std::cout << "operator << (const T&)" << std::endl;
   return *this; }
};

int main()
{
  CFoo f;
  f << "Число" << 5 ;

  char* c = 0;
  f << c;
}

должна печатать:
operator << (const char *)
operator << (int)
operator << (const char *)

безо всяких фокусов.

Или ты подразумеваешь проблемы какого-нибудь конкретного компилятора? Опять же, почему тогда не добавлены перегруженные версии для всех арифметических типов, ведь с ними будут те же "проблемы"?
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[5]: Перегрузить <<
От: Шахтер Интернет  
Дата: 07.12.03 20:11
Оценка:
Здравствуйте, Павел Кузнецов, Вы писали:

ПК>Здравствуйте, Шахтер, Вы писали:


ПК>>>А зачем обе версии: и operator << (char *x), и operator << (const char *x)?


ПК>Например, следующая программа:

ПК>
ПК>#include <iostream>

ПК>class CFoo
ПК>{
ПК>public:
ПК> CFoo & operator << (int x) {
ПК>   std::cout << "operator << (int)" << std::endl;
ПК>   return *this; }

ПК> CFoo & operator << (const char *x)  {
ПК>   std::cout << "operator << (const char *)" << std::endl;
ПК>   return *this; }

ПК> template<class T>
ПК> CFoo & operator << (const T&) {
ПК>   std::cout << "operator << (const T&)" << std::endl;
ПК>   return *this; }
ПК>};

ПК>int main()
ПК>{
ПК>  CFoo f;
ПК>  f << "Число" << 5 ;

ПК>  char* c = 0;
ПК>  f << c;
ПК>}
ПК>

ПК>должна печатать:
ПК>
ПК>operator << (const char *)
ПК>operator << (int)
ПК>operator << (const char *)
ПК>

ПК>безо всяких фокусов.

ПК>Или ты подразумеваешь проблемы какого-нибудь конкретного компилятора? Опять же, почему тогда не добавлены перегруженные версии для всех арифметических типов, ведь с ними будут те же "проблемы"?


Насчет должна не знаю, мне влом заниматься очередным исследованием стандарта. Да и написать лишнюю строчку, чтобы компилятор не напрягал мозги -- не большая проблема.
Вот выход VC++ 7.1

operator << (const char *)
operator << (int)
operator << (const T&)
Press any key to continue


Насчет арифметических типов -- верно, надо их всех перегрузить. Чтобы не увеличивать объём кода, надо определить семейство базовых функций форматирования

void put(const char *);
void put(int);
void put(unsigned int);
void put(long long); // или __int64
void put(unsigned long long); // или unsigned __int64


А в соответствующих операторах вызывать подходящие версии put.
... << RSDN@Home 1.1.0 stable >>
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[6]: Перегрузить <<
От: Павел Кузнецов  
Дата: 08.12.03 09:57
Оценка:
Здравствуйте, Шахтер, Вы писали:

ПК>>>> А зачем обе версии: и operator << (char *x), и operator << (const char *x)?


ПК>> Например, следующая программа: <...> должна печатать:

ПК>>
 ПК>> operator << (const char *)
 ПК>> operator << (int)
 ПК>> operator << (const char *)
 ПК>>

ПК>> безо всяких фокусов.

Ш> Насчет должна не знаю, мне влом заниматься очередным исследованием стандарта.


Похоже, не так уж и должна. Похоже мы с Comeau немного ошиблись: его новая версия ведет
себя так же, как VC++7.1, и свежий GCC.

ПК>> Опять же, почему тогда не добавлены перегруженные версии для всех арифметических

ПК>> типов, ведь с ними будут те же "проблемы"?

Ш> Насчет арифметических типов -- верно, надо их всех перегрузить.


По-моему, лучше просто лишний раз не заморачиваться с шаблоном operator <<

Но если, все-таки, подразумевалось делегирование << стандартному потоку, придется
еще и operator << для манипуляторов предоставить...
Posted via RSDN NNTP Server 1.7 "Bedlam"
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re: Перегрузить <<
От: Lorenzo_LAMAS  
Дата: 08.12.03 10:02
Оценка:
Здравствуйте, Аноним, Вы писали:

Может, перегрузить его дважды?

class A
{
public:
   A & operator <<(const char *);
   A & operator <<(int);
};
Of course, the code must be complete enough to compile and link.
Re[7]: Перегрузить <<
От: Lorenzo_LAMAS  
Дата: 08.12.03 10:20
Оценка:
Подождите, что-то я не догоняю. Есть две функции, одна принимает const char *, другая шаблон и принимает const T &. "число" имеет тип const char[6]. Разве ж для него не должна вызваться шаблонная функция? Ведь для нее не нужно никаких преобразований?
Of course, the code must be complete enough to compile and link.
Re[5]: Перегрузить <<
От: jazzer Россия Skype: enerjazzer
Дата: 08.12.03 10:29
Оценка:
Здравствуйте, Павел Кузнецов, Вы писали:

ПК>Здравствуйте, Шахтер, Вы писали:


ПК>>>А зачем обе версии: и operator << (char *x), и operator << (const char *x)? :???:


Ш>>Затем, что если ещё добавить


Ш>>
Ш>>template <class T>
Ш>>CFoo & operator << (const T &x) { ... return *this; }
Ш>>


Ш>>то начнутся проблемы.


ПК>Хм... Какие?


ПК>Например, следующая программа:

ПК>
ПК>#include <iostream>

ПК>class CFoo
ПК>{
ПК>public:
ПК> CFoo & operator << (int x) {
ПК>   std::cout << "operator << (int)" << std::endl;
ПК>   return *this; }

ПК> CFoo & operator << (const char *x)  {
ПК>   std::cout << "operator << (const char *)" << std::endl;
ПК>   return *this; }

ПК> template<class T>
ПК> CFoo & operator << (const T&) {
ПК>   std::cout << "operator << (const T&)" << std::endl;
ПК>   return *this; }
ПК>};

ПК>int main()
ПК>{
ПК>  CFoo f;
ПК>  f << "Число" << 5 ;

ПК>  char* c = 0;
ПК>  f << c;
ПК>}
ПК>

ПК>должна печатать:
ПК>
ПК>operator << (const char *)
ПК>operator << (int)
ПК>operator << (const char *)
ПК>

ПК>безо всяких фокусов.

ПК>Или ты подразумеваешь проблемы какого-нибудь конкретного компилятора? Опять же, почему тогда не добавлены перегруженные версии для всех арифметических типов, ведь с ними будут те же "проблемы"?


насколько я понимаю, тут срабатывает преобразование char * -> char * const &, а не char * -> const char *
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[6]: Перегрузить <<
От: Павел Кузнецов  
Дата: 08.12.03 11:01
Оценка:
Здравствуйте, jazzer, Вы писали:

ПК>> Например, следующая программа: <...>

ПК>> должна печатать:
ПК>>
 ПК>> operator << (const char *)
 ПК>> operator << (int)
 ПК>> operator << (const char *)
 ПК>>

ПК>> безо всяких фокусов.

j> насколько я понимаю, тут срабатывает преобразование char * -> char * const &, а не char * -> const char *


Похоже на то, но и я, и прошлая версия Comeau думали, что "обычная" функция (не шаблон) "выигрывала",
т.к. соответствующее преобразование имело тот же ранг (Exact Match). Судя по всему, это, все-таки,
не так, и шаблон является лучшим кандидатом — надо будет копнуть поглубже, как только будет время.
Posted via RSDN NNTP Server 1.7 "Bedlam"
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[7]: Перегрузить <<
От: jazzer Россия Skype: enerjazzer
Дата: 08.12.03 12:15
Оценка:
Здравствуйте, Павел Кузнецов, Вы писали:

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


ПК>>> Например, следующая программа: <...>

ПК>>> должна печатать:
ПК>>>
 ПК>>> operator << (const char *)
 ПК>>> operator << (int)
 ПК>>> operator << (const char *)
 ПК>>>

ПК>>> безо всяких фокусов.

j>> насколько я понимаю, тут срабатывает преобразование char * -> char * const &, а не char * -> const char *


ПК>Похоже на то, но и я, и прошлая версия Comeau думали, что "обычная" функция (не шаблон) "выигрывала",

ПК>т.к. соответствующее преобразование имело тот же ранг (Exact Match). Судя по всему, это, все-таки,
ПК>не так, и шаблон является лучшим кандидатом — надо будет копнуть поглубже, как только будет время.

для нешаблонной функции надо ведь еще преобразование lvalue to rvalue, а для шаблонной — только навесить квалификатор
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[8]: Перегрузить <<
От: Павел Кузнецов  
Дата: 08.12.03 12:39
Оценка:
Здравствуйте, Lorenzo_LAMAS, Вы писали:

LL> Подождите, что-то я не догоняю. Есть две функции, одна принимает const char *, другая шаблон

LL> и принимает const T &. "число" имеет тип const char[6]. Разве ж для него не должна вызваться
LL> шаблонная функция? Ведь для нее не нужно никаких преобразований?

Array-to-pointer имеет ранг Exact Match, поэтому с точки зрения перегрузки эти две функции равны. Например:
void f(const char*);
void f(const char(&)[6]);

int main()
{
  f("число");
}

"ComeauTest.c", line 6: error: more than one instance of overloaded function "f"
          matches the argument list, the choices that match are:
            function "f(const char *)"
            function "f(const char (&)[6])"
            The argument types that you used are: (const char [6])
    f("число");
    ^


В случае же когда одна из этих функций является специализацией шаблона, вторая "выигрывает", т.к.,
грубо говоря, при прочих равных, "обычные" функции (не шаблоны) имеют преимущество перед шаблонами.
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[8]: Перегрузить <<
От: Павел Кузнецов  
Дата: 08.12.03 12:43
Оценка:
Здравствуйте, jazzer, Вы писали:

j>>> насколько я понимаю, тут срабатывает преобразование char * -> char * const &, а не char * -> const char *


ПК>> Похоже на то, но и я, и прошлая версия Comeau думали, что "обычная" функция (не шаблон) "выигрывала",

ПК>> т.к. соответствующее преобразование имело тот же ранг (Exact Match). Судя по всему, это, все-таки,
ПК>> не так, и шаблон является лучшим кандидатом — надо будет копнуть поглубже, как только будет время.

j> для нешаблонной функции надо ведь еще преобразование lvalue to rvalue,

j> а для шаблонной — только навесить квалификатор

Это все преобразования ранга Exact Match; здесь есть что-то еще. Также см. http://rsdn.ru/forum/?mid=471103
Автор: Павел Кузнецов
Дата: 08.12.03
Posted via RSDN NNTP Server 1.7 "Bedlam"
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[7]: Перегрузить <<
От: Шахтер Интернет  
Дата: 09.12.03 02:51
Оценка:
Здравствуйте, Павел Кузнецов, Вы писали:

ПК>Здравствуйте, Шахтер, Вы писали:


ПК>>>>> А зачем обе версии: и operator << (char *x), и operator << (const char *x)?


ПК>>> Например, следующая программа: <...> должна печатать:

ПК>>>
 ПК>>> operator << (const char *)
 ПК>>> operator << (int)
 ПК>>> operator << (const char *)
 ПК>>>

ПК>>> безо всяких фокусов.

Ш>> Насчет должна не знаю, мне влом заниматься очередным исследованием стандарта.


ПК>Похоже, не так уж и должна. Похоже мы с Comeau немного ошиблись: его новая версия ведет

ПК>себя так же, как VC++7.1, и свежий GCC.

Похоже, здесь. В принципе, логично, поскольку навешивание const модификатора сужает множество операций над объектом (вообще говоря, значительно).

13.3.3.2

Two implicit conversion sequences of the same form are indistinguishable conversion sequences unless one
of the following rules apply:
— Standard conversion sequence S1 is a better conversion sequence than standard conversion sequence
S2 if


— S1 is a proper subsequence of S2 (comparing the conversion sequences in the canonical form
defined by 13.3.3.1.1, excluding any Lvalue Transformation; the identity conversion sequence is
considered to be a subsequence of any nonidentity
conversion sequence) or, if not that,
— the rank of S1 is better than the rank of S2 (by the rules defined below), or, if not that,

— S1 and S2 differ only in their qualification conversion and yield similar types T1 and T2 (4.4),
respectively, and the cvqualification
signature of type T1 is a proper subset of the cvqualification
signature of type T2, [Example:
int f(const int *);
int f(int *);
int i;
int j = f(&i); // Calls f(int *)
—end example] or, if not that,
... << RSDN@Home 1.1.0 stable >>
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[9]: Великий и могучий
От: Lorenzo_LAMAS  
Дата: 09.12.03 08:49
Оценка:
ПК>>> не так, и шаблон является лучшим кандидатом — надо будет копнуть поглубже, как только будет время.


void fun(const int *);
void fun(const int * &);

void g()
{
    int * p = 0;
    fun(p);
}


Черт, никакая медитация не помогает понять, в чем тут дело. В одном случае — Lvalue преобразование, потом квалификация, в другом binding с добавлением квалификации. Почему воторое лучше первого?
Of course, the code must be complete enough to compile and link.
Re[10]: Великий и могучий
От: Lorenzo_LAMAS  
Дата: 09.12.03 08:55
Оценка:
Вообще беда — оба вижуала (6.0/7.0) выбрали вторую функцию, а icc первую.
Of course, the code must be complete enough to compile and link.
Re[10]: Великий и могучий
От: achp  
Дата: 09.12.03 09:02
Оценка:
Здравствуйте, Lorenzo_LAMAS, Вы писали:

ПК>>>> не так, и шаблон является лучшим кандидатом — надо будет копнуть поглубже, как только будет время.


L_L>
L_L>void fun(const int *);
L_L>void fun(const int * &);

L_L>void g()
L_L>{
L_L>    int * p = 0;
L_L>    fun(p);
L_L>}
L_L>


L_L>Черт, никакая медитация не помогает понять, в чем тут дело. В одном случае — Lvalue преобразование, потом квалификация, в другом binding с добавлением квалификации. Почему воторое лучше первого?


Это очень скверно. Позволяет ненароком снять константность.
Да здравствует ИМХО!
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.