why static_cast needed here to produce proper output

N

nin234ATIyahoo.com

Hi all
I have a logger class and facing the following issue

enum eErrLvl
{
eLOG_DEBUG_5 = 1,
eLOG_DEBUG_4,
eLOG_DEBUG_3,
eLOG_DEBUG_2,
eLOG_DEBUG_1,
eLOG_INFO,
eLOG_WARNING,
eLOG_ERROR,
eLOG_FATAL
};


std::eek:stream&
operator << (std::eek:stream& os, eErrLvl& eLvl)
{
switch (eLvl)
{
case eLOG_DEBUG_5:
os << "Debug_5\t: ";
break;
case eLOG_DEBUG_4:
os << "Debug_4\t: ";
break;
case eLOG_DEBUG_3:
os << "Debug_3\t: ";
break;
case eLOG_DEBUG_2:
os << "Debug_2\t: ";
break;
case eLOG_DEBUG_1:
os << "Debug_1\t: ";
break;
case eLOG_INFO:
os << "Info\t: ";
break;
case eLOG_WARNING:
os << "Warn\t: ";
break;
case eLOG_ERROR:
os << "Error\t: ";
break;
case eLOG_FATAL:
os << "Fatal\t: ";
break;
}
return os;
}

class srvLog
{
static int volatile nLglvl;

//volatile keyword is a hint to compiler an object may change the
value
//in a way not specified by the language and aggressive
optimizations
//must be avoided

eErrLvl nSeverity;
public:
friend std::eek:stream& operator << (std::eek:stream& , const
srvLog&);

};
std::eek:stream& operator << (std::eek:stream& os, const srvLog& oLog)
{
os << "initial msg " << static_cast<eErrLvl>(oLog.nSeverity);
return os;
}
My problem is with this statement
os << "initial msg " << static_cast<eErrLvl>(oLog.nSeverity);

Only when I use the static_cast does it invoke the operator (<<) for
the enum. Otherwise it just prints the integer value corresponding to
the enum
ie if I use
os << "initial msg " << (oLog.nSeverity);

Ninan
 
V

Victor Bazarov

nin234ATIyahoo.com said:
[...]
My problem is with this statement
os << "initial msg " << static_cast<eErrLvl>(oLog.nSeverity);

Only when I use the static_cast does it invoke the operator (<<) for
the enum. Otherwise it just prints the integer value corresponding to
the enum
ie if I use
os << "initial msg " << (oLog.nSeverity);

The compiler promotes 'nSeverity' to 'int' and finds that there is
operator << among the members of 'ostream', and uses it to output
the value. If you static_cast it, the compiler is prevented from
promoting the enum to int. IIRC.

V
 
N

nin234ATIyahoo.com

actually ; that precisly is my question. Why does the compiler promote
the enum to int, when there is already an operator defined for it
 
V

Victor Bazarov

nin234ATIyahoo.com said:
actually ; that precisly is my question. Why does the compiler promote
the enum to int, when there is already an operator defined for it

Hard to say, a bug in the compiler, maybe?
 
?

=?iso-8859-1?Q?Ali_=C7ehreli?=

nin234ATIyahoo.com said:
Hi all
I have a logger class and facing the following issue

enum eErrLvl
{
eLOG_DEBUG_5 = 1,
eLOG_DEBUG_4,
eLOG_DEBUG_3,
eLOG_DEBUG_2,
eLOG_DEBUG_1,
eLOG_INFO,
eLOG_WARNING,
eLOG_ERROR,
eLOG_FATAL
};


std::eek:stream&
operator << (std::eek:stream& os, eErrLvl& eLvl)
{

Change the type of eLvl to either

eErrLvl const &

or

eErrLvl

of which, probably the latter is better for an enum.
switch (eLvl)
{
case eLOG_DEBUG_5:
[...]

std::eek:stream& operator << (std::eek:stream& os, const srvLog& oLog)
{
os << "initial msg " << static_cast<eErrLvl>(oLog.nSeverity);

oLog is const is this context, so is oLog.nSeverity. The compiler cannot
dispatch operator<< that takes a non-const eErrLvl (as you wrote.)

The change above should fix the problem.
return os;
}
My problem is with this statement
os << "initial msg " << static_cast<eErrLvl>(oLog.nSeverity);

Only when I use the static_cast does it invoke the operator (<<) for
the enum. Otherwise it just prints the integer value corresponding to
the enum
ie if I use
os << "initial msg " << (oLog.nSeverity);

Ali
 
A

Andrey Tarasevich

nin234ATIyahoo.com said:
actually ; that precisly is my question. Why does the compiler promote
the enum to int, when there is already an operator defined for it

You 'operator <<' for 'eErrLvl' type is declared as

std::eek:stream& operator << (std::eek:stream& os, eErrLvl& eLvl)

Note that it takes its second argument by non-constant reference.

At the same time 'operator <<' for 'srvLog' takes its second operand by
constant reference

std::eek:stream& operator << (std::eek:stream& os, const srvLog& oLog)

Now, inside the latter operator you are trying to do the following

os << "initial msg " << oLog.nSeverity;

But compiler cannot call the former operator in this case for an obvious
reason: the "constness" of 'oLog' propagates to 'oLog.nSeverity',
meaning that 'oLog.nSeverity' is considered to be a const-qualified
value. Compiler cannot bind a non-constant parameter to a constant
argument in the 'operator <<' call.

Instead, it has to seek a workaround solution, which presents itself in
form of a standard 'enum -> int' conversion followed by a call to
'operator <<' for 'int's. The compiler is behaving correctly in this case.

Strictly speaking, your 'static_cast' is not supposed to change
anything. The result of that cast is not an lvalue and non-constant
reference still cannot be bound to it. I don't understand why you
compiler suddenly decides to choose your operator after the cast. _This_
looks like a bug in the compiler.

If you want the compiler to use your 'operator <<' for 'eErrLvl', you
have to declare it as either

std::eek:stream& operator << (std::eek:stream& os, eErrLvl eLvl)

or

std::eek:stream& operator << (std::eek:stream& os, const eErrLvl& eLvl)

I'd stick with the first variant. There absolutely no reason to use a
reference here, especially a non-constant one. How did you come to an
idea to pass the 'eErrLvl' value as 'eErrLvl&' reference in the first place?
 

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

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top