Operator function taking references shall accept literals too

Hi,

I'm working on an output stream class just like ostream. For formatted output I use the << operator taking a reference as argument (e.g. "&int").

Now I want this operator function to accept also int literals like 12345. How can I achieve this? I know there must be a way cause with ostream it works just fine. Ostream also deals with references as described in the documentation on this site but I can also write for example cout << 12345.

Thanks in advance!


you can if you pass by const reference, but with basic types doesn't make much sense
Thanks! But why wouldn't it make sense??
Because it's a waste of time and (sometimes) memory. You could just pass it by value. It has the same cost (4 bytes) and it saves you the hidden dereferencing operation that has to be done every time you access something by a reference.
Last edited on
Oh, that's interesting for me, I always thought references were faster. Strange then, ostream use references though...
Passing by references is faster for large complex objects because the object does not need to be copied. For tiny objects like int this does not apply. Copying an int is faster than copying a reference to an int and dereferencing it.

However, this only makes a difference if the functions in question are not inlined.
For inlined functions, passing by constant reference and passing by value does not result in different assembly code (only for simple objects!). So if your class is header-only, just don't worry about it.
Last edited on
Baltram wrote:
ostream use references though...

For basic types? Where does it do that?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
//...

// [27.6.2.5.2] arithmetic inserters
      /**
       *  @name Arithmetic Inserters
       *
       *  All the @c operator<< functions (aka <em>formatted output
       *  functions</em>) have some common behavior.  Each starts by
       *  constructing a temporary object of type std::basic_ostream::sentry.
       *  This can have several effects, concluding with the setting of a
       *  status flag; see the sentry documentation for more.
       *
       *  If the sentry status is good, the function tries to generate
       *  whatever data is appropriate for the type of the argument.
       *
       *  If an exception is thrown during insertion, ios_base::badbit
       *  will be turned on in the stream's error state without causing an
       *  ios_base::failure to be thrown.  The original exception will then
       *  be rethrown.
      */
      //@{
      /**
       *  @brief  Basic arithmetic inserters
       *  @param  A variable of builtin type.
       *  @return  @c *this if successful
       *
       *  These functions use the stream's current locale (specifically, the
       *  @c num_get facet) to perform numeric formatting.
      */
      __ostream_type& 
      operator<<(long __n);
      
      __ostream_type& 
      operator<<(unsigned long __n);

      __ostream_type& 
      operator<<(bool __n);

      __ostream_type& 
      operator<<(short __n)
      { 
	ios_base::fmtflags __fmt = this->flags() & ios_base::basefield;
	if (__fmt & ios_base::oct || __fmt & ios_base::hex)
	  return this->operator<<(static_cast<unsigned long>
				  (static_cast<unsigned short>(__n)));
	else
	  return this->operator<<(static_cast<long>(__n));
      }

      __ostream_type& 
      operator<<(unsigned short __n)
      { return this->operator<<(static_cast<unsigned long>(__n)); }

      __ostream_type& 
      operator<<(int __n)
      { 
	ios_base::fmtflags __fmt = this->flags() & ios_base::basefield;
	if (__fmt & ios_base::oct || __fmt & ios_base::hex)
	  return this->operator<<(static_cast<unsigned long>
				  (static_cast<unsigned int>(__n)));
	else
	  return this->operator<<(static_cast<long>(__n));
      }

      __ostream_type& 
      operator<<(unsigned int __n)
      { return this->operator<<(static_cast<unsigned long>(__n)); }

#ifdef _GLIBCXX_USE_LONG_LONG
      __ostream_type& 
      operator<<(long long __n);

      __ostream_type& 
      operator<<(unsigned long long __n);
#endif

      __ostream_type& 
      operator<<(double __f);

      __ostream_type& 
      operator<<(float __f)
      { return this->operator<<(static_cast<double>(__f)); }

      __ostream_type& 
      operator<<(long double __f);

      __ostream_type& 
      operator<<(const void* __p);

//... 
@Athar
Thx!
m4ster r0shi wrote:
For basic types? Where does it do that?
In the documentation of this site it looks like it did use references (http://www.cplusplus.com/reference/iostream/ostream/operator%3C%3C/). Might be wrong though...
Indeed... That's what it looks like... I wonder if someone knows if there is any good reason for that... (Athar?)
In the documentation of this site it looks like it did use references (http://www.cplusplus.com/reference/iostream/ostream/operator%3C%3C/ ). Might be wrong though...
It is wrong, here is from the C++ standards:
27.6.2.5.2 Arithmetic Inserters
operator<<(bool val);
operator<<(short val);
operator<<(unsigned short val);
operator<<(int val);
operator<<(unsigned int val);
operator<<(long val);
operator<<(unsigned long val);
operator<<(float val);
operator<<(double val);
operator<<(long double val);
operator<<(const void* val);


However, this only makes a difference if the functions in question are not inlined.
For inlined functions, passing by constant reference and passing by value does not result in different assembly code (only for simple objects!). So if your class is header-only, just don't worry about it.
You can't know if the compiler really inlines your functions so you do need to worry about it
Last edited on
Topic archived. No new replies allowed.