By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
432,257 Members | 928 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 432,257 IT Pros & Developers. It's quick & easy.

ambiguous types: want automatic conversion

P: n/a
I think this is a question about automatic type conversion, but I
didn't find the answer after googling for these words ...

I have a class called Value (source see below) which can hold an int
or a string:
Value i(23);
Value s("blah");

Now I want an implicit conversion that automatically returns the
correct type, even in a context like this:
std::cout << i; // works
std::cout << s; // doesn't work: "Not an int" exception thrown

I think this should be feasible because the object knows what to
return (it was constructed with the certain type, although that's only
at runtime, not compile time ...). Of course, I could have an
asString(), or an asInt() method in the class, but I want to avoid
that as it seems redundant. I also don't want to use external (non-
std) packages like boost.

Thanks for any help! The class I have so far is this:

class Value {
std::string stringValue;
int intValue;
bool isString;
bool isInt;
public:
Value(std::string s) : isString(true), isInt(false),
stringValue(s) {}
Value(int i) : isString(false), isInt(true), intValue(i) {}
operator std::string (){
if(!isString){throw std::runtime_error("Not a string");}
return stringValue;
}
operator int (){
if(!isInt){throw std::runtime_error("Not an int");}
return intValue;
}
};

Sep 20 '07 #1
Share this Question
Share on Google+
3 Replies


P: n/a
Hi,
"Markus Dehmann" <ma************@gmail.comwrote in message
news:11**********************@g4g2000hsf.googlegro ups.com...
>I think this is a question about automatic type conversion, but I
didn't find the answer after googling for these words ...

I have a class called Value (source see below) which can hold an int
or a string:
Value i(23);
Value s("blah");

Now I want an implicit conversion that automatically returns the
correct type, even in a context like this:
std::cout << i; // works
std::cout << s; // doesn't work: "Not an int" exception thrown

I think this should be feasible because the object knows what to
return (it was constructed with the certain type, although that's only
at runtime, not compile time ...). Of course, I could have an
asString(), or an asInt() method in the class, but I want to avoid
that as it seems redundant. I also don't want to use external (non-
std) packages like boost.

Thanks for any help! The class I have so far is this:

class Value {
std::string stringValue;
int intValue;
bool isString;
bool isInt;
public:
Value(std::string s) : isString(true), isInt(false),
stringValue(s) {}
Value(int i) : isString(false), isInt(true), intValue(i) {}
operator std::string (){
if(!isString){throw std::runtime_error("Not a string");}
return stringValue;
}
operator int (){
if(!isInt){throw std::runtime_error("Not an int");}
return intValue;
}
};
Yes that is possible. Just create a friend function like in my own variant
class
//------------------------ Header----------------------
class UVar
{
friend std::ostream& operator<<( std::ostream& Output, const UVar& Var );
};
std::ostream& operator<<( std::ostream& Output, const UVar& Var );
//-----------------Source
std::ostream& operator<<( std::ostream& Output, const UVar& Var )
{
Var.Print( Output );

return Output;
}
void UVar::Print( ostream& Output ) const
{

switch( Type )
{
case eNull:
Output << "Null";
break;
case eLong:
Output << Long;
break;
case eDouble:
Output << Double;
break;
case eString:
Output << *reinterpret_cast<const std::string*>( String );
break;
case eMap:;
{
Output << "Map : ";

const map<UVar*,UVar*, UFindVarMap1 =
*reinterpret_cast<map<UVar*,UVar*, UFindVarconst *const>( Map );

for( map<UVar*,UVar*, UFindVar>::const_iterator VarIter = Map1.begin();
VarIter != Map1.end(); ++VarIter )
{
Output << "Key(" << VarIter->first->type_name() << ") = " <<
*VarIter->first << " Value{ " << VarIter->second->type_name() << ") = <"
<< *VarIter->second << ">";
}
}
break;
case eSRefPtr:
Output << "Object Classname = " << (
*reinterpret_cast<MSRefPtr<ISerialize>const*>( SRefPtr ) ?
(*reinterpret_cast<MSRefPtr<ISerialize>const*>( SRefPtr ) )->GetClassname()
: string( "SRefPtr is null" ) );
break;
case eWRefPtr:
Output << "Object Classname = " << (
*reinterpret_cast<MWRefPtr<ISerialize>const*>( WRefPtr ) ?
(*reinterpret_cast<MWRefPtr<ISerialize>const*>( WRefPtr ) )->GetClassname()
: string( "WRefPtr is null" ) );
break;
case eKey:
Output << "MKey " << *reinterpret_cast<MKey const *>( KeyStroke );
break;
default:
Channel << Chan1 << "Unknown type in UVar type = " << static_cast<int>(
Type ) << End;
throw CInfoException( "Unknown type" );
}
}
Regards, Ron AF Greve

http://www.InformationSuperHighway.eu
Sep 20 '07 #2

P: n/a
On Sep 21, 10:26 am, Markus Dehmann <markus.dehm...@gmail.comwrote:
std::cout << i; // works
std::cout << s; // doesn't work: "Not an int" exception thrown

class Value {
std::string stringValue;
int intValue;
bool isString;
bool isInt;
public:
Value(std::string s) : isString(true), isInt(false),
stringValue(s) {}
Value(int i) : isString(false), isInt(true), intValue(i) {}
operator std::string (){
if(!isString){throw std::runtime_error("Not a string");}
return stringValue;
}
operator int (){
if(!isInt){throw std::runtime_error("Not an int");}
return intValue;
}
};
Well, this code will work. However it is quite obfuscated.

operator<< for std::ostream accepts both int and std::string.
However, int is selected because it is a builtin type. If
you had another conversion , e.g. operator double(), defined
you would get an ambiguous error.

It would be better to make the logic more explicit, i.e.
define operator<<(std::ostream &, Value) .

Sep 20 '07 #3

P: n/a

"Markus Dehmann" <ma************@gmail.comwrote in message
news:11**********************@g4g2000hsf.googlegro ups.com...
>I think this is a question about automatic type conversion, but I
didn't find the answer after googling for these words ...

I have a class called Value (source see below) which can hold an int
or a string:
Value i(23);
Value s("blah");

Now I want an implicit conversion that automatically returns the
correct type, even in a context like this:
std::cout << i; // works
std::cout << s; // doesn't work: "Not an int" exception thrown
Switch to boost::variant which has an insertion operator(untested)

#include <boost/variant.hpp>
#include <string>
#include <ostream>

int main()
{
boost::variant<int,std::stringv;

v = std::string("abc");

std::cout << v << std::endl;

v = 123;

std::cout << v << std::endl;

}

Jeff Flinn
Sep 20 '07 #4

This discussion thread is closed

Replies have been disabled for this discussion.