Velocity Reviews > C++ > Template notation

# Template notation

desktop
Guest
Posts: n/a

 04-23-2007
I am trying to understand the following template:

template <typename T>
inline T const& max (T const& a, T const& b) {
return a < b ? b : a;
}

does it say that the function max returns a constant reference to T of
any type?

I have never seen a function returning references before, does it mean
that it returns the address of the value returned?

normally the address of eg. an integer is:

int x = 22;

&x

but in the above function its more like:

x&

=?iso-8859-1?q?Erik_Wikstr=F6m?=
Guest
Posts: n/a

 04-23-2007
On 23 Apr, 14:30, desktop <(E-Mail Removed)> wrote:
> I am trying to understand the following template:
>
> template <typename T>
> inline T const& max (T const& a, T const& b) {
> return a < b ? b : a;
>
> }
>
> does it say that the function max returns a constant reference to T of
> any type?

It returns a const reference of type T, yes.

> I have never seen a function returning references before, does it mean
> that it returns the address of the value returned?

No, pointers are not references, a reference can be seen as an alias
for a variable, so the following is true for references but not for
pointers:

int i = 1;
int& j = i; // j is a reference to i
if (&i == &j)
// Always true

So you can see that if you take the address of a reference to an
object you get the address of the object while if you take the address
of a pointer to a object you get that pointer's address.

Another example:

void foo(int& i) {
++i;
}

int k = 1;

foo(k);

Now, in the function foo(), the i we are changing is the same integer
as k, so it's another name but the same variable.

--
Erik Wikström

desktop
Guest
Posts: n/a

 04-23-2007
Erik Wikström wrote:
> On 23 Apr, 14:30, desktop <(E-Mail Removed)> wrote:
>> I am trying to understand the following template:
>>
>> template <typename T>
>> inline T const& max (T const& a, T const& b) {
>> return a < b ? b : a;
>>
>> }
>>
>> does it say that the function max returns a constant reference to T of
>> any type?

>
> It returns a const reference of type T, yes.
>
>> I have never seen a function returning references before, does it mean
>> that it returns the address of the value returned?

>
> No, pointers are not references, a reference can be seen as an alias
> for a variable, so the following is true for references but not for
> pointers:
>
> int i = 1;
> int& j = i; // j is a reference to i
> if (&i == &j)
> // Always true
>
> So you can see that if you take the address of a reference to an
> object you get the address of the object while if you take the address
> of a pointer to a object you get that pointer's address.
>
> Another example:
>
> void foo(int& i) {
> ++i;
> }
>
> int k = 1;
>
> foo(k);
>
> Now, in the function foo(), the i we are changing is the same integer
> as k, so it's another name but the same variable.
>
> --
> Erik Wikström
>

Ok guess it the same as in java where Object myobj = new Object()
generates the reference myobj to an Object.

The parameters to the max template:

max (T const& a, T const& b)

are also references, why pass a reference to a template instead of the
"real" object?

Victor Bazarov
Guest
Posts: n/a

 04-23-2007
desktop wrote:
> [..]
> Ok guess it the same as in java where Object myobj = new Object()
> generates the reference myobj to an Object.

I don't think it's appropriate to say that. There are no references
in Java (Just like there are no pointers in Java).

> The parameters to the max template:
>
> max (T const& a, T const& b)
>
> are also references, why pass a reference to a template instead of the
> "real" object?

Please see FAQ section 8, section 31, the rest of it too. If you have

V
--

Salt_Peter
Guest
Posts: n/a

 04-23-2007
On Apr 23, 9:13 am, desktop <(E-Mail Removed)> wrote:
> Erik Wikström wrote:
> > On 23 Apr, 14:30, desktop <(E-Mail Removed)> wrote:
> >> I am trying to understand the following template:

>
> >> template <typename T>
> >> inline T const& max (T const& a, T const& b) {
> >> return a < b ? b : a;

>
> >> }

>
> >> does it say that the function max returns a constant reference to T of
> >> any type?

>
> > It returns a const reference of type T, yes.

>
> >> I have never seen a function returning references before, does it mean
> >> that it returns the address of the value returned?

>
> > No, pointers are not references, a reference can be seen as an alias
> > for a variable, so the following is true for references but not for
> > pointers:

>
> > int i = 1;
> > int& j = i; // j is a reference to i
> > if (&i == &j)
> > // Always true

>
> > So you can see that if you take the address of a reference to an
> > object you get the address of the object while if you take the address
> > of a pointer to a object you get that pointer's address.

>
> > Another example:

>
> > void foo(int& i) {
> > ++i;
> > }

>
> > int k = 1;

>
> > foo(k);

>
> > Now, in the function foo(), the i we are changing is the same integer
> > as k, so it's another name but the same variable.

>
> > --
> > Erik Wikström

>
> Ok guess it the same as in java where Object myobj = new Object()
> generates the reference myobj to an Object.

Java might call that a reference, its closer to a C++ pointer.
Java has no equivalence of a C++ reference.

>
> The parameters to the max template:
>
> max (T const& a, T const& b)
>
> are also references, why pass a reference to a template instead of the
> "real" object?

Its the other way around. passing by reference IS passing the "real"
variable using an alias.
Passing by value only modifies a local variable and more importantly -
it invokes a constructor, usually a copy ctor.

Juha Nieminen
Guest
Posts: n/a

 04-24-2007
Salt_Peter wrote:
> Passing by value only modifies a local variable and more importantly -
> it invokes a constructor, usually a copy ctor.

Quite curiously, passing by reference may in some cases actually
produce less efficient code (depending on the compiler, of course).

Using gcc 3.3.5 with maximum optimizations (-O3 -march=pentium4)
this code:

template<typename T>
inline const T& max(T const& a, T const& b) { return a < b ? b : a; }
int foo(int a, int b) { return max(a, b); }

produces this asm:

..LFB5:
pushl %ebp
..LCFI0:
movl %esp, %ebp
..LCFI1:
movl 12(%ebp), %edx
leal 8(%ebp), %eax
leal 12(%ebp), %ecx
cmpl %edx, 8(%ebp)
popl %ebp
cmovge %eax, %ecx
movl (%ecx), %eax
ret

Removing the references should *in theory* produce an identical
result, but it doesn't. The code:

template<typename T>
inline const T max(T const a, T const b) { return a < b ? b : a; }
int foo(int a, int b) { return max(a, b); }

produces this asm:

..LFB5:
pushl %ebp
..LCFI0:
movl %esp, %ebp
..LCFI1:
movl 8(%ebp), %ecx
movl 12(%ebp), %eax
popl %ebp
cmpl %eax, %ecx
cmovge %ecx, %eax
ret

The 10 opcodes have been reduced to 8. Granted, I'm not a Pentium4
expert and I can't tell for sure that the latter code is faster than
the former, but I'm pretty convinced.

Salt_Peter
Guest
Posts: n/a

 04-24-2007
On Apr 23, 11:45 pm, Juha Nieminen <(E-Mail Removed)> wrote:
> Salt_Peter wrote:
> > Passing by value only modifies a local variable and more importantly -
> > it invokes a constructor, usually a copy ctor.

>
> Quite curiously, passing by reference may in some cases actually
> produce less efficient code (depending on the compiler, of course).
>
> Using gcc 3.3.5 with maximum optimizations (-O3 -march=pentium4)
> this code:
>
> template<typename T>
> inline const T& max(T const& a, T const& b) { return a < b ? b : a; }
> int foo(int a, int b) { return max(a, b); }
>
> produces this asm:
>
> .LFB5:
> pushl %ebp
> .LCFI0:
> movl %esp, %ebp
> .LCFI1:
> movl 12(%ebp), %edx
> leal 8(%ebp), %eax
> leal 12(%ebp), %ecx
> cmpl %edx, 8(%ebp)
> popl %ebp
> cmovge %eax, %ecx
> movl (%ecx), %eax
> ret
>
> Removing the references should *in theory* produce an identical
> result, but it doesn't. The code:
>
> template<typename T>
> inline const T max(T const a, T const b) { return a < b ? b : a; }
> int foo(int a, int b) { return max(a, b); }
>
> produces this asm:
>
> .LFB5:
> pushl %ebp
> .LCFI0:
> movl %esp, %ebp
> .LCFI1:
> movl 8(%ebp), %ecx
> movl 12(%ebp), %eax
> popl %ebp
> cmpl %eax, %ecx
> cmovge %ecx, %eax
> ret
>
> The 10 opcodes have been reduced to 8. Granted, I'm not a Pentium4
> expert and I can't tell for sure that the latter code is faster than
> the former, but I'm pretty convinced.

With simple variables thats expected and in this case pass by value is
fine if T remains a primitive type. The moment you start passing
complex variables by value (and invoking additional copy constructors)
the results won't be the same.