template question

G

graham

Hi,

can anybody please explain why the following prints 4, 3, 2, 1, 0 and
not 0, 1, 2, 3, 4

I like what this does but don't understand why the values are assigned
the values in the order they are?

cheers

Graham

class type2intbase {
template <typename T>
friend struct type2int;

static const int next() {
static int id = 0; return id++;
}
};

template <typename T>
struct type2int {
static const int value() {
static const int id = type2intbase::next(); return id;
}
};


struct foo{};
struct foo1{};
struct foo2{};
struct foo3{};
struct foo4{};

#include <iostream>
using namespace std;

int main(int argc, char** argv)
{

type2int<foo> zero;
type2int<foo1> one;
type2int<foo2> two;
type2int<foo3> three;
type2int<foo4> four;

cout << zero.value() << " " << one.value() << " " << two.value()
<< " " << three.value() << " " << four.value() << " " << endl;
return 0;
}
 
J

Juha Nieminen

graham said:
can anybody please explain why the following prints 4, 3, 2, 1, 0 and
not 0, 1, 2, 3, 4
cout << zero.value() << " " << one.value() << " " << two.value()
<< " " << three.value() << " " << four.value() << " " << endl;

Because that's equivalent to:

operator<<(operator<<(operator<<(operator<<(cout, four.value()), three.value()), two.value()), one.value());
 
G

graham

  Because that's equivalent to:

operator<<(operator<<(operator<<(operator<<(cout, four.value()), three.value()), two.value()), one.value());

Fair enoughski, but I'd like to know how the values are assigned. If I
do this with the above code;

cout << zero.value() << " " << one.value() << " " << four.value() <<
" " << endl;

I get

2 1 0

"zero" is now 2
"one" is now 1
"four" is still 0

I'd like to know the why, there's something going on behind the scenes
I'm not gettin'

Cheers

GrahamO
 
B

bartek szurgot

On 11/29/2011 10:24 AM, graham wrote:
[...]
cout << zero.value() << " " << one.value() << " " << two.value()
<< " " << three.value() << " " << four.value() << " " << endl;

according to to standard it is unspecified in which order will the
arguments of the calls be evaluated. to make things simpler - having:
void f(int,int);
code:
f( one.value(), two.value() )
can call:
f(0, 1)
as well as
f(1, 0)
in general you can get any permutation of evaluation order. it depends
on the compiler. performing calls left-to-right or right-to-left is
easiest, thus most often used by vendors. and so your code, may
accidentally work on some compilers versions.

for example your code gives 4 3 2 1 0 on gcc and 0 1 2 3 4 on clang.
both of them are fine, since you cannot depend on evaluation order in
this case.

if your calls have side effects, first compute values, in required
order, and then pass it as arguments.
 
G

graham

On 11/29/2011 10:24 AM, graham wrote:
[...]
   cout << zero.value() <<  " " << one.value() << " " << two.value()
<< " " << three.value() << " " << four.value() << " " << endl;

according to to standard it is unspecified in which order will the
arguments of the calls be evaluated. to make things simpler - having:
void f(int,int);
code:
f( one.value(), two.value() )
can call:
f(0, 1)
as well as
f(1, 0)
in general you can get any permutation of evaluation order. it depends
on the compiler. performing calls left-to-right or right-to-left is
easiest, thus most often used by vendors. and so your code, may
accidentally work on some compilers versions.

for example your code gives 4 3 2 1 0 on gcc and 0 1 2 3 4 on clang.
both of them are fine, since you cannot depend on evaluation order in
this case.

if your calls have side effects, first compute values, in required
order, and then pass it as arguments.

--
pozdrawiam serdecznie / best regards,
Bartek 'BaSz' Szurgot

http://www.baszerr.org

Awesome! Thanks a million, thats the reply I was looking for.

This;


type2int<foo> zero;
int a = zero.value();
type2int<foo1> one;
int b = one.value();
type2int<foo2> two;
int c = two.value();
type2int<foo3> three;
int d = three.value();
type2int<foo4> four;
int e = four.value();

cout << a << " " << b << " " << c << " " << d << " " << e << endl;
cout << zero.value() << " " << one.value() << " " << four.value() <<
" " << endl;

outputs;

0 1 2 3 4
0 1 4

Which is what I wanted.

thanks a million Bartek, have a nice day

Graham
 
J

Juha Nieminen

bartek szurgot said:
if your calls have side effects, first compute values, in required
order, and then pass it as arguments.

The easier solution is to simply split the std::cout call:

std::cout << zero.value() << " ";
std::cout << one.value() << " ";
std::cout << two.value() << " ";
std::cout << three.value() << " ";
std::cout << four.value() << std::endl;

The moral of the story is that you should never use functions that have
side effects as several parameters to another function (taking more than
one parameter).
 
J

Juha Nieminen

graham said:
type2int<foo> zero;
int a = zero.value();
type2int<foo1> one;
int b = one.value();
type2int<foo2> two;
int c = two.value();
type2int<foo3> three;
int d = three.value();
type2int<foo4> four;
int e = four.value();

cout << a << " " << b << " " << c << " " << d << " " << e << endl;
cout << zero.value() << " " << one.value() << " " << four.value() <<
" " << endl;

As I said in my other post, that's the hard way of doing it. Just do it
like this:

std::cout << zero.value() << " ";
std::cout << one.value() << " ";
std::cout << two.value() << " ";
std::cout << three.value() << " ";
std::cout << four.value() << std::endl;
 
G

graham

  As I said in my other post, that's the hard way of doing it. Just do it
like this:

std::cout << zero.value() << " ";
std::cout << one.value() << " ";
std::cout << two.value() << " ";
std::cout << three.value() << " ";
std::cout << four.value() << std::endl;

thanks but Bartek hit the nail on the head. His explanation was spot
on. Thanks anyways

have a nice day.

G
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top