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_limits<T> m_limits;
T m_bit;
// other fns/ctor's etc
template<class C> operator C() const
throw(InvalidCastException)
{
if(std::numeric_limits<C>::digits < m_limits.digits)
{
throw InvalidCastException(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::boolalpha<<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. 5 3002
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.
* 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_limits<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(InvalidCastException)
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>::digits < m_limits.digits)
See above regarding 'm_limits'.
{ throw InvalidCastException(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::boolalpha<<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?
> > ---------------------------------------------------------- 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_limits<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(InvalidCastException)
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>::digits < m_limits.digits)
See above regarding 'm_limits'.
{ throw InvalidCastException(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::boolalpha<<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.
* 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?
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<typename 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. This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
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...
|
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...
|
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 >)
{
}
|
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 );
}
|
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...
|
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 &)
|
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.
...
|
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,...
|
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...
|
by: DolphinDB |
last post by:
Tired of spending countless mintues downsampling your data? Look no further!
In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
|
by: isladogs |
last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM).
In this month's session, we are pleased to welcome back...
|
by: Vimpel783 |
last post by:
Hello!
Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
|
by: jfyes |
last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
|
by: PapaRatzi |
last post by:
Hello,
I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
|
by: Defcon1945 |
last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
|
by: Shællîpôpï 09 |
last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
|
by: af34tf |
last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
|
by: isladogs |
last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM).
In this session, we are pleased to welcome former...
| |