473,626 Members | 3,276 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

template conversion operator clarification needed

Hello,

I have come back to C++ after a couple of years with Java so I am quite
rusty and this question may seem poor:

My platform is Windows XP with MSVC 7.1.

I have a class with a templatized conversion operator defined as
follows:

----------------------------------------------------------
template<class T>
class IBitImpl : public virtual IBit<T>
{
std::numeric_li mits<T> m_limits;
T m_bit;
// other fns/ctor's etc

template<class C> operator C() const
throw(InvalidCa stException)
{
if(std::numeric _limits<C>::dig its < m_limits.digits )
{
throw InvalidCastExce ption(L"Invalid argument -
Destination type C cannot accomodate source type T. ");
}
return (C) m_bit;
}
};
----------------------------------------------------------

So, I up and write a simple test:

----------------------------------------------------------
int x = 121234234;
IBitImpl<int> lowbit2(2);
bool isset = (1 == (x & lowbit2));
std::cout<<"Is bit "<<lowbit2.Bit( )<<" in "<<x<<" set?
"<<std::boolalp ha<<isset<<std: :endl;
----------------------------------------------------------

I get an error indicating that there is an ambiguity because in (x &
lowbit2) the conversion can be any one of (long, bool, unsigned long,
etc).

I thought that the compiler looks at x and upcasts lowbit2 to the
appropriate type (in this case int). This doesn't seem to be the case
here.

I figured the whole problem ws because of the conversion operator
defined above. Consequently, I changed the expression to make the case
explicit as follows:

---------------------------------------------------------
bool isset = (1 == (x & (int) lowbit2));
---------------------------------------------------------

which needless to say, worked fine. However, I don't understand why the
correct cast isn't automatically applied. I am missing something here
and would appreciate it if someone would point me in the right
direction.

thanks,

-vijai.

Aug 6 '05 #1
5 3026
My stupidity. The code snippet for the expression should be

bool isset = ( (x & (int) lowbit2));

However, that doesn't detract from my original question.

-vijai.

Aug 7 '05 #2
* Vijai Kalyan:

I have come back to C++ after a couple of years with Java
Noted.

so I am quite
rusty and this question may seem poor:

My platform is Windows XP with MSVC 7.1.
Irrelevant.

I have a class with a templatized conversion operator defined as
follows:

----------------------------------------------------------
template<class T>
class IBitImpl : public virtual IBit<T>
Naming: "Bit" would be a good name for this class.
Performance/design: difficult to see any advantage in having IBit<T>.
{
std::numeric_li mits<T> m_limits;
Should be a 'typedef' (if anything), not a data member.

T m_bit;
Naming: is this the bit number, let's call it n, or is it the bit
value 1<<n?

Only for the latter case does it make sense to use type T.

In the test program it seems there is a member function that computes n from
m_bit, which is a bit awkward, opposite of the simplest & most efficient.

// other fns/ctor's etc

template<class C> operator C() const
throw(InvalidCa stException)
Javaism : avoid throw specifications in C++, except 'throw()'.
Design : don't be afraid to use 'assert'.
Types : if possible use standard exception classes or classes derived from
them, e.g. here, std::bad_cast (but: rather 'assert' instead).
{
if(std::numeric _limits<C>::dig its < m_limits.digits )
See above regarding 'm_limits'.

{
throw InvalidCastExce ption(L"Invalid argument -
Destination type C cannot accomodate source type T. ");
See above regarding exception types and use of 'assert'.

}
return (C) m_bit;
Javaism (and also C-ism): don't use C-style casts. Use e.g. static_cast.

See above regarding naming and resulting confusion about what 'm_bit' is.
}
};
----------------------------------------------------------

So, I up and write a simple test:

----------------------------------------------------------
int x = 121234234;
IBitImpl<int> lowbit2(2);
bool isset = (1 == (x & lowbit2));
std::cout<<"Is bit "<<lowbit2.Bit( )<<" in "<<x<<" set?
"<<std::boolalp ha<<isset<<std: :endl;
----------------------------------------------------------

I get an error indicating that there is an ambiguity because in (x &
lowbit2) the conversion can be any one of (long, bool, unsigned long,
etc).
Yes. Built-in operators do not constrain the types of their arguments,
except to the set of types the operator in question is defined for.
However, if you define your own '&' operator you can do that, e.g.

template< typename T, typename U >
T operator&( T a, Bit<U> const& b ){ return a & static_cast<T>( b ); }

template< typename T, typename U >
U operator&( Bit<T> const& a, U b ){ return static_cast<U>( a ) & b; }

I thought that the compiler looks at x and upcasts lowbit2 to the
'upcast' is something else entirely; here you're talking about a conversion,
in no particular direction.

appropriate type (in this case int). This doesn't seem to be the case
here.

I figured the whole problem ws because of the conversion operator
defined above. Consequently, I changed the expression to make the case
explicit as follows:

---------------------------------------------------------
bool isset = (1 == (x & (int) lowbit2));
---------------------------------------------------------

which needless to say, worked fine. However, I don't understand why the
correct cast isn't automatically applied.
There is no correct conversion because there is no constraint whatsoever
(except to the set of types that the built-in '&' is defined for).

I am missing something here
and would appreciate it if someone would point me in the right
direction.


See above.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Aug 7 '05 #3
> > ----------------------------------------------------------
template<class T>
class IBitImpl : public virtual IBit<T>
Naming: "Bit" would be a good name for this class.
Performance/design: difficult to see any advantage in having IBit<T>.


Well, IBit is really the interface that defines the requirements for
IBitImpl.

template<class T>
class IBit
{
public:
template<class C> IBit<T>& operator=(C);
template<class C> IBit<T>& operator=(const IBit<C>&);
template<class C> operator C() const;

virtual inline T Bit() const = 0;
virtual inline T Mask() const = 0;
};
{
std::numeric_li mits<T> m_limits;
Your are right. A member is not called for.
Should be a 'typedef' (if anything), not a data member.

T m_bit;
Naming: is this the bit number, let's call it n, or is it the bit
value 1<<n?


m_bit is the bit number. There is a data member m_mask that stores the
mask.
Only for the latter case does it make sense to use type T.
Here, I don't know. I presume an 'int' or 'short' can equally hold all
possible bit numbers.
In the test program it seems there is a member function that computes n from
m_bit, which is a bit awkward, opposite of the simplest & most efficient.
No. The mask is computed when the object is created and stored in
m_mask of type T.
// other fns/ctor's etc

template<class C> operator C() const
throw(InvalidCa stException)


Javaism : avoid throw specifications in C++, except 'throw()'.
Design : don't be afraid to use 'assert'.
Types : if possible use standard exception classes or classes derived from
them, e.g. here, std::bad_cast (but: rather 'assert' instead).


True. I should have used bad_cast. On the other hand, most of the
standard exception classes don't seem to have a wide-string variant of
their constructors. I would rather not mix the two and prefer to use
the wide-string variant where possible. Of course, that is irrelevant
strictly speaking. I can derive form bad_cast and provide a
wide-string constructor.
{
if(std::numeric _limits<C>::dig its < m_limits.digits )


See above regarding 'm_limits'.

{
throw InvalidCastExce ption(L"Invalid argument -
Destination type C cannot accomodate source type T. ");


See above regarding exception types and use of 'assert'.

}
return (C) m_bit;


Javaism (and also C-ism): don't use C-style casts. Use e.g. static_cast.


My mistake.
See above regarding naming and resulting confusion about what 'm_bit' is.


As I said, m_bit is the bit number. m_mask is the actual mask. So,

m_mask = (1 << m_bit);
}
};
----------------------------------------------------------

So, I up and write a simple test:

----------------------------------------------------------
int x = 121234234;
IBitImpl<int> lowbit2(2);
bool isset = (1 == (x & lowbit2));
std::cout<<"Is bit "<<lowbit2.Bit( )<<" in "<<x<<" set?
"<<std::boolalp ha<<isset<<std: :endl;
----------------------------------------------------------

I get an error indicating that there is an ambiguity because in (x &
lowbit2) the conversion can be any one of (long, bool, unsigned long,
etc).


Yes. Built-in operators do not constrain the types of their arguments,
except to the set of types the operator in question is defined for.
However, if you define your own '&' operator you can do that, e.g.

template< typename T, typename U >
T operator&( T a, Bit<U> const& b ){ return a & static_cast<T>( b ); }

template< typename T, typename U >
U operator&( Bit<T> const& a, U b ){ return static_cast<U>( a ) & b; }

I thought that the compiler looks at x and upcasts lowbit2 to the


'upcast' is something else entirely; here you're talking about a conversion,
in no particular direction.


Ah, I see. Ok. Well, I thought about defining those operators and then
started wondering why the conversion operator wouldn't work in general.
Of course, that means I would have to define a | operator as well.
appropriate type (in this case int). This doesn't seem to be the case
here.

I figured the whole problem ws because of the conversion operator
defined above. Consequently, I changed the expression to make the case
explicit as follows:

---------------------------------------------------------
bool isset = (1 == (x & (int) lowbit2));
---------------------------------------------------------

which needless to say, worked fine. However, I don't understand why the
correct cast isn't automatically applied.


There is no correct conversion because there is no constraint whatsoever
(except to the set of types that the built-in '&' is defined for).

I am missing something here
and would appreciate it if someone would point me in the right
direction.


See above.


Great! Thanks a lot for the clarifications.

-vijai.

Aug 7 '05 #4
* Vijai Kalyan:
}
return (C) m_bit;


Javaism (and also C-ism): don't use C-style casts. Use e.g. static_cast.


My mistake.
See above regarding naming and resulting confusion about what 'm_bit' is.


As I said, m_bit is the bit number. m_mask is the actual mask. So,

m_mask = (1 << m_bit);


In that case, in the test program's

bool isset = (1 == (x & lowbit2));


the sub-expression (I've added the necessary static_cast)

x & static_cast<int >( lowbit2 )

will not give correct result, because x isn't and'ed with a mask but with a
bitnumber.

This particular bug would probably have been avoided with more descriptive
naming... ;-)

There's also another bug in that expression, namely, the comparision with 1.

To avoid silly warnings from the compiler you can

A) compare the '&' result with the mask, or
B) compare the '&' result with 0, or
C) apply the negation operator '!' twice to the '&' result.

To avoid such bugs in general, try to design classes where it requires great
effort to use them incorrectly -- e.g., take control of all relevant ops.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Aug 7 '05 #5
As a matter of fact, it is kind of funny.

The conversion operator actually returns the "mask" instead of the
"bit". So,

(x & lowbit2)

would work.

But that is not really why I replied.

Considering that in the above expression, an explicit cast is required
to use the mask writting the correct expression as:

x & (int) lowbit2

really enforces a certain amount of safety primarily because the
conversion operator applied checks to make sure that the destination
type (in this case int) can actually hold the mask. I would think that
is actually a "good side-effect" of the conversion operator although I
am not too sure.

For example, the following would most definitely throw a runtime
exception "bad_cast"

char x = 'a';
x & (char) lowbit2.

Likewise, so would the following:

IBitImpl<int> lowbiti(2);
IBitImpl<char> lowbitc = lowbiti;

This of course not being due to the conversion operator but due to the
templatized constructor:

template<typena me C> IBitImpl(const IBitImpl<C>&)

which also performs the check that C can hold T.

However, the following wouldn't:

IBitImpl<char> lowbitc(2);
IBitImpl<int> lowbiti = lowbitc;

since an integer mask can certainly accomodate a char mask.

Interesting no?

-vijai.

Aug 8 '05 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

21
2158
by: Makhno | last post by:
Hello, Why does my cast from Vector<class Float> to Vector<float> not work? It won't compile, template<class Float> class Vector { public: Vector(Float x1,Float y1,Float z1):x(x1),y(y1),z(z1){} inline Vector<float> operator() () const;
15
3077
by: iuweriur | last post by:
A few questions on the curiously recurring template pattern: This page: http://c2.com/cgi/wiki?CuriouslyRecurringTemplate this part: template<typename T> struct ArithmeticType { T operator + (const T& other) const {
3
1923
by: BigMan | last post by:
Here is a piece of code: #include <memory> using namespace std; template< typename SomeType > void f(auto_ptr_ref< SomeType >) { }
3
1382
by: Kevin Ruland | last post by:
Hi all. I have a template class with conversion operator: template< typename T > class FooWrapper { public: FooWrapper( const T& rhs ); }
3
2026
by: CoolPint | last post by:
After upgrading to gcc 3.4.2 from gcc 3.2.3, I got compiler errors that I could not figure out. After reading other postings, I learned that my coding was not compliant to the standard in the first place and I did fix many of them, especially with the proper use of the keyword "typename". But I have one problem I have no idea how to fix. I created below a simpler coding which demonstrates my problem: The coding below used to compile...
6
4424
by: YUY0x7 | last post by:
Hi, I am having a bit of trouble with a specialization of operator<<. Here goes: class MyStream { }; template <typename T> MyStream& operator<<(MyStream& lhs, T const &)
3
3933
by: Chris | last post by:
I am having a very strange problem involving virtual functions in template classes. First of all, here is an extremely simplified structure of the two classes I am having problems with. template<class Type> class base { public: base& operator/=(const base&); Type *image;
12
1870
by: Jim Langston | last post by:
I have a template I call StrmConvert, which uses std::stringstream to convert from any type to any other type that can be used by stringstring. This is what it looks like: template<typename T, typename F > T StrmConvert( F from ) { std::stringstream temp; temp << from; T to = T(); temp >> to;
3
3748
by: Hamilton Woods | last post by:
Diehards, I developed a template matrix class back around 1992 using Borland C++ 4.5 (ancestor of C++ Builder) and haven't touched it until a few days ago. I pulled it from the freezer and thawed it out. I built a console app using Microsoft Visual C++ 6 (VC++) and it worked great. Only one line in the header file had to be commented out. I built a console app using Borland C++ Builder 5. The linker complained of references to...
0
8269
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
8203
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
8711
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
1
8368
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
8512
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
4094
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
4206
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
2630
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
1
1815
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.