Substitute 'float'?

G

Glen Able

Should it be possible to create a custom class, 'Float', which would behave
as a drop-in replacement for the builtin float type?

As mentioned in another thread, I once tried this in rather a hurry to try
and catch some floating point naughtiness, but was stumped in various
places. Is there a fundamental obstacle to doing this?

thanks,
G.A.
 
V

Victor Bazarov

Glen said:
Should it be possible to create a custom class, 'Float', which would behave
as a drop-in replacement for the builtin float type?

Yes, basically.
As mentioned in another thread, I once tried this in rather a hurry to try
and catch some floating point naughtiness, but was stumped in various
places. Is there a fundamental obstacle to doing this?

Not that I can recall. Some would probably claim the legendary
performance decrease when using classes versus built-in types, but
IMO it's not always true. Given a good compiler and implementation
you should get the same performance.

V
 
A

Andrey Tarasevich

Glen said:
Should it be possible to create a custom class, 'Float', which would behave
as a drop-in replacement for the builtin float type?

As mentioned in another thread, I once tried this in rather a hurry to try
and catch some floating point naughtiness, but was stumped in various
places. Is there a fundamental obstacle to doing this?
...

One fundamental obstacle that comes to mind is variadic functions.
Passing non-POD classes as variadic arguments results in udefined behavior.

Otherwise, it appears to be doable.
 
J

JKop

Glen Able posted:
Should it be possible to create a custom class, 'Float', which would
behave as a drop-in replacement for the builtin float type?

As mentioned in another thread, I once tried this in rather a hurry to
try and catch some floating point naughtiness, but was stumped in
various places. Is there a fundamental obstacle to doing this?

thanks,
G.A.

I don't understand, what do you mean by "a drop-in replacment"? Made me
think of:

typedef float Float;

Do you want to have a float which cannot contain certain values? Something
like:

class SpecialFloat
{
private:

float data;

public:

SpecialFloat& operator=(float input)
{
if (input != 666)
{
data = input;
}
}

operator float const()
{
return data;
}
};


Or maybe you're looking for something different altogether...


-JKop
 
J

Julie

Andrey said:
One fundamental obstacle that comes to mind is variadic functions.
Passing non-POD classes as variadic arguments results in udefined behavior.

I was not aware of that. Not that I write many variadic functions...

Good to know, nonetheless.
 
R

Rolf Magnus

Julie said:
I was not aware of that. Not that I write many variadic functions...

No, but you might have the idea to pass one of your objects to printf
one day. Another thing that comes to mind is conversions. The rules for
built-in types are different from the rules for user defined types.
 
E

E. Robert Tisdale

Glen said:
Should it be possible to create a custom class, 'Float',
Is this a valid as a drop-in replacement for the builtin float type?

I have done this many times.

#include "Float.h"
#define float Float
As mentioned in another thread,
I once tried this in rather a hurry to try
and catch some floating point naughtiness,
but was stumped in various places.

Can you show us an example?
Is there a fundamental obstacle to doing this?

No.

The abstraction used in the C++ computer programming language
to define a portable "built-in" type float virtually guarantees
that you can substitute your own definition of float as long as
you implement the abstract data type defined by the standard.
 
G

Glen Able

Glen Able said:
Should it be possible to create a custom class, 'Float', which would behave
as a drop-in replacement for the builtin float type?

As mentioned in another thread, I once tried this in rather a hurry to try
and catch some floating point naughtiness, but was stumped in various
places. Is there a fundamental obstacle to doing this?

thanks,
G.A.

OK, I've had another go at implementing this...


Here's problem #1:

Clearly I need to have this constructor:

Float(float value) { m_value = value; }

But the existence of this means that any unions containing a 'Float' will be
invalid, whereas they were OK with 'float'.


Problem #2 seems more fundamental:

To allow sqrt etc. to work, I seem to require

operator float() { return m_value; }

Which causes massive problems of ambiguity regarding conversions.



By the way, would anyone else care to give this substitution a quick try on
their own code (so, define the Float class, then redefine float as Float)?
I think it'd be an interesting exercise to see what other issues this throws
up, especially since so many people seem to think this should be
unproblematic!

cheers,
G.A.
 
J

JKop

E. Robert Tisdale posted:

#define float Float


Disgusting.


We have:

inline functions
global const variables
typedefs
tempates

for a reason.


typedef float SpecialFloat;
 
J

JKop

Glen Able posted:
OK, I've had another go at implementing this...


Here's problem #1:

Clearly I need to have this constructor:

Float(float value) { m_value = value; }

But the existence of this means that any unions containing a 'Float'
will be invalid, whereas they were OK with 'float'.

No problem there. There'd be a problem with virtual functions though... but
ofcourse that isn't a virtual function.


union
{
SpecialFloat j;

int p;
} cow;


cow.p = 42;

cow.j = 45.6;

Problem #2 seems more fundamental:

To allow sqrt etc. to work, I seem to require

operator float() { return m_value; }

Which causes massive problems of ambiguity regarding conversions.


I don't see what you're on about. If a function wants a float:

SpecialFloat t;

Func(t);

What's wrong with that?

Or:

SpecialFloat k;
float t;

float r = k + t;

Again here, it's converted to a float


By the way, would anyone else care to give this substitution a quick
try on their own code (so, define the Float class, then redefine float
as Float)? I think it'd be an interesting exercise to see what other
issues this throws up, especially since so many people seem to think
this should be unproblematic!

cheers,
G.A.

Did my own example not show that? This is kindergarden stuff.


-JKop
 
K

Karl Heinz Buchegger

JKop said:
Glen Able posted:


No problem there. There'd be a problem with virtual functions though... but
ofcourse that isn't a virtual function.

union
{
SpecialFloat j;

int p;
} cow;

That's not legal. The constructor of SpecialFloat is non trivial and thus
SpecialFloat cannot be used inside a union.

Unfortunately the OP is correct. Using such a special class in a union
is almost always a problem. Luckily this case seldome arises in practice.
I don't see what you're on about. If a function wants a float:

SpecialFloat t;

Func(t);

What's wrong with that?

Creating such conversion operators needs to be done with
great care. By introducing them, you enable the compiler
to convert parameters even in cases where you don't want
them to happen. This is exactly the reason why eg. std::string
has no conversion operator to const char*, but a member function
c_str() instead.
 
K

Karl Heinz Buchegger

Karl said:
Creating such conversion operators needs to be done with
great care. By introducing them, you enable the compiler
to convert parameters even in cases where you don't want
them to happen. This is exactly the reason why eg. std::string
has no conversion operator to const char*, but a member function
c_str() instead.

To emphasize on that further.

Consider the following situation:

#include <iostream>
using namespace std;

class SpecialFloat
{
public:
SpecialFloat( float Val = 0.0f ) : m_Value( Val ) {};
float ToFloat() { return m_Value; }

friend SpecialFloat operator+( const SpecialFloat& lhs, const SpecialFloat& rhs );

private:
float m_Value;
};

SpecialFloat operator+( const SpecialFloat& lhs, const SpecialFloat& rhs )
{
return lhs.m_Value + rhs.m_Value;
}

int main()
{
SpecialFloat a( 1.0f );
float b;

b = ( a + 2.0f ).ToFloat();
}

All is well.
Then some clever programmer decides that the call of ToFloat is ugly, and that somebody
has to do something about it: introduce operator float():

#include <iostream>
using namespace std;

class SpecialFloat
{
public:
SpecialFloat( float Val = 0.0f ) : m_Value( Val ) {};
float ToFloat() { return m_Value; }

friend SpecialFloat operator+( const SpecialFloat& lhs, const SpecialFloat& rhs );

operator float() { return m_Value; }

private:
float m_Value;
};

SpecialFloat operator+( const SpecialFloat& lhs, const SpecialFloat& rhs )
{
return lhs.m_Value + rhs.m_Value;
}

int main()
{
SpecialFloat a( 1.0f );
float b;

b = a + 2.0f;
}

But now the whole thing no longer compiles.
Why?
Because the compiler now has to equally good ways to translate
b = a + 2.0f;

it could either

a) using the constructor, convert 2.0f to a SpecialFloat object and applying
the user defined operator+ on both SpecialFloat objects

or

b) convert a from SpecialFloat to an ordinary float by using the conversion
operator float() on a and using the builtin operator+ for floats.
 
R

Richard Herring

JKop <[email protected]> said:
E. Robert Tisdale posted:




Disgusting.

Agreed. Redefining keywords is asking for trouble. It's probably also in
breach of 17.4.3.1.1.
We have:

inline functions
global const variables
typedefs
tempates

for a reason.


typedef float SpecialFloat;

But that doesn't satisfy the OP's requirement for a custom *class*.
 
J

JKop

Karl Heinz Buchegger posted:

class SpecialFloat
{
public:
SpecialFloat( float Val = 0.0f ) : m_Value( Val ) {};

explicit SpecialFloat( float Val = 0.0f ) : m_Value( Val ) {};


Without spending too much time on the subject - I'm trying to get through
Bjarne's book.
 
K

Karl Heinz Buchegger

JKop said:
Karl Heinz Buchegger posted:


explicit SpecialFloat( float Val = 0.0f ) : m_Value( Val ) {};

Then, with the example given, you can no longer write:
b = a + 2.0f;
Since the implicite constructor is no longer available.
The compiler chooses the way of converting b to a float
and does the addition by using the operator+ for builtin float
types. Thus the custom written operator+ is effectively useless
in this situation. You have to force the compiler to use it
by writing
b = a + SpecialFloat( 2.0f );
Not very intuitive.

When in doubt, I prefer implicite creation due the use
of constructors against implicit conversion with
conversion operators.
 

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,768
Messages
2,569,574
Members
45,051
Latest member
CarleyMcCr

Latest Threads

Top