473,386 Members | 1,654 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,386 software developers and data experts.

Built in type inheritance.

For various reasons I'd like to be able to inherit from the built in
types, which obviously you cannot do. To get around this, I made a
template to emulate the built in types. So far I can't find any
situations in which this template fails to work interchangably with the
built in types. My question is if anyone knows of any gotcha type
situations in which this is going to fail.

Thanks,
Alan

template <typename T>
class built_in
{
private :
T value ;
public :

built_in() {}
built_in(const T &t) : value(t) {}

operator T() const { return value ; }
operator T&() { return value ; }

T &operator=(const T &t) { return (value = t) ; }
T &operator %=(const T &t) { return value %= t ; }
T &operator &=(const T &t) { return value &= t ; }
T &operator |=(const T &t) { return value |= t ; }
T &operator ^=(const T &t) { return value ^= t ; }
T &operator +=(const T &t) { return value += t ; }
T &operator -=(const T &t) { return value -= t ; }
T &operator *=(const T &t) { return value *= t ; }
T &operator /=(const T &t) { return value /= t ; }
T &operator <<=(const T &t) { return value <<= t ; }
T &operator >>=(const T &t) { return value >>= t ; }
T* operator&() { return &value } ;
} ;
Jul 23 '05 #1
6 2076
"Alan Johnson" <al**@undisclosed.com> wrote in message
news:d6**********@news.Stanford.EDU
For various reasons I'd like to be able to inherit from the built in
types, which obviously you cannot do. To get around this, I made a
template to emulate the built in types. So far I can't find any
situations in which this template fails to work interchangably with
the built in types. My question is if anyone knows of any gotcha type
situations in which this is going to fail.

Thanks,
Alan

template <typename T>
class built_in
{
private :
T value ;
public :

built_in() {}
built_in(const T &t) : value(t) {}

operator T() const { return value ; }
operator T&() { return value ; }

T &operator=(const T &t) { return (value = t) ; }
T &operator %=(const T &t) { return value %= t ; }
T &operator &=(const T &t) { return value &= t ; }
T &operator |=(const T &t) { return value |= t ; }
T &operator ^=(const T &t) { return value ^= t ; }
T &operator +=(const T &t) { return value += t ; }
T &operator -=(const T &t) { return value -= t ; }
T &operator *=(const T &t) { return value *= t ; }
T &operator /=(const T &t) { return value /= t ; }
T &operator <<=(const T &t) { return value <<= t ; }
T &operator >>=(const T &t) { return value >>= t ; }
T* operator&() { return &value } ;
} ;


You are missing a semi-colon in your final operator.

The fact that you need a conversion operator in order to get the value will
prevent the compiler from making other conversions that it would make if the
built in type were used. Consider the following:

// define your class template here
#include <iostream>
class Test
{
public:
Test(int x) : x_(x)
{}
void Print() const
{
std::cout << x_ << std::endl;
}
private:
int x_;
};

void foo(const Test & test)
{
test.Print();
}

int main()
{
built_in<int> n(3);
foo(3); // compiles since Test constructor with int parameter is called
foo(n); // won't compile since compiler will not do two conversions ---
// from built_in<int> to int and then from int to Test.
}

--
John Carson

Jul 23 '05 #2
"John Carson" <jc****************@netspace.net.au> wrote in message
news:d6***********@otis.netspace.net.au
int main()
{
built_in<int> n(3);
foo(3); // compiles since Test constructor with int parameter is called
foo(n); // won't compile since compiler will not do two conversions ---
// from built_in<int> to int and then from int to Test.
}

You can work around this with a cast:

foo((Test)n);

but some of the convenience is lost.

--
John Carson

Jul 23 '05 #3

"Alan Johnson" <al**@undisclosed.com> schrieb im Newsbeitrag news:d6**********@news.Stanford.EDU...
template <typename T>
class built_in
{ [...] T* operator&() { return &value } ;
} ;


That will make it difficult to get the address of an instance of some built_in<T>. You should add a member function to get an object's address, like

// inside class built_in
built_in* GetAddress() { return this; }
built_in const* GetAddress() const { return this; }

Or better (IMHO) remove operator&() and add a member function to get the address of the value member, like

T* Pointer() { return &value; }
T const* Pointe() const [ return &value; }

Regards
Heinz
Jul 23 '05 #4
> For various reasons I'd like to be able to inherit from the built in
types, which obviously you cannot do.


I'm curious to know what these various reasons are...

--
Jonathan
[FAQ] - http://www.parashift.com/c++-faq-lite/

Jul 23 '05 #5
Jonathan Mcdougall wrote:
For various reasons I'd like to be able to inherit from the built in
types, which obviously you cannot do.

I'm curious to know what these various reasons are...

--
Jonathan
[FAQ] - http://www.parashift.com/c++-faq-lite/


Two reasons come to mind immediately. First, I'd like to be able to add
arbitrary elements to the domain of a type. Just an off the top of my
head example, some shortest path algorithms rely on dynamically updating
the distance between two graph nodes with the best distance found so
far. To initialize such an algorithm, you set the current best distance
between two points at infinity. Because the 'int' type doesn't have a
representation for infinity, one possible workaround would be to create
a type that inherits from int (were that possible) and add a flag to
indicate infinity. However, you'd like for that type to behave like an
int in all cases except when testing it against infinity.

Another reason would be to make semantically distinct types. For
example, I might write a program that uses the unsigned type for both
the purpose of storing the dimensions of an image, and also for
providing indices into an array. Under normal circumstances these
should never be interchangable. Dimensions of an image have nothing to
do with array indices (in our theoretical example) and any assignment
between the two is a runtime error. It would be nice if we could
inherit from int to make two distinct types that, while both behaving
like integers, were distinct as far as the type checking system was
concerned. Then any assignment between the two would become a compile
time error, which is far preferable.

For a better example of types that differ only in semantics, I recommend
Joel Spolsky's article: http://www.joelonsoftware.com/articles/Wrong.html

He recommends using a naming convention to keep encoded and unencoded
strings separate. I think a more robust system would be to create
different types, that both behaved like (inherited from) strings, but
could not be used interchangably with each other.

-Alan
Jul 23 '05 #6
"Alan Johnson" <al**@undisclosed.com> wrote in message
news:d6**********@news.Stanford.EDU
Jonathan Mcdougall wrote:
For various reasons I'd like to be able to inherit from the built in
types, which obviously you cannot do.

I'm curious to know what these various reasons are...

--
Jonathan


Two reasons come to mind immediately. First, I'd like to be able to
add arbitrary elements to the domain of a type. Just an off the top
of my head example, some shortest path algorithms rely on dynamically
updating the distance between two graph nodes with the best distance
found so far. To initialize such an algorithm, you set the current
best distance between two points at infinity. Because the 'int' type
doesn't have a representation for infinity, one possible workaround
would be to create a type that inherits from int (were that possible)
and add a flag to indicate infinity. However, you'd like for that
type to behave like an int in all cases except when testing it
against infinity.


Or you could initialise the value of the int to

std::numeric_limits<unsigned int>::max()

(declared in the limits header). If this isn't as large as your shortest
path, you have a problem anyway.
Another reason would be to make semantically distinct types. For
example, I might write a program that uses the unsigned type for both
the purpose of storing the dimensions of an image, and also for
providing indices into an array. Under normal circumstances these
should never be interchangable. Dimensions of an image have nothing
to do with array indices (in our theoretical example) and any
assignment between the two is a runtime error. It would be nice if
we could inherit from int to make two distinct types that, while both
behaving like integers, were distinct as far as the type checking
system was concerned. Then any assignment between the two would
become a compile time error, which is far preferable.


There is a suggestion before the standards committee to create an extended
form of typedef that would create a new type (as opposed to merely an alias
for a type, which is what the current typedef does). This would be an
alternative and simpler way to get the type safety you seek.

I don't mean to dispute that having built-in types as fully fledged classes
would have some advantages (another one that springs to mind is gaining full
control over initialisation).

--
John Carson

Jul 23 '05 #7

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

Similar topics

59
by: Michael C | last post by:
eg void DoIt() { int i = FromString("1"); double d = FromString("1.1"); } int FromString(string SomeValue) {
3
by: Achim Dahlhoff | last post by:
Hi. I'm trying to find out the diffrence between normal classes and classes derived from built-in types. (Which is causing me trouble trying to instantiate a class using C API calls) >>>...
4
by: Frank-René Schäfer | last post by:
-- A class needs to have N members according to N types mentioned in a typelist (possibly with one type occuring more than once). -- The classes should be generated **avoiding** multiple...
5
by: Martin Jørgensen | last post by:
Hi, Consider this code: --- beginning of code --- #include <iostream> using namespace std; class Child{ public:
18
by: Jordan | last post by:
In OOP literature we read frequently about "interface" - a term which is apparently used to mean different things depending on context and possibly language. ..NET however provides for the...
8
by: Kris Jennings | last post by:
Hi, I am trying to create a new generic class and am having trouble casting a generic type to a specific type. For example, public class MyClass<Twhere T : MyItemClass, new() { public...
4
by: zaeminkr | last post by:
I got a good answer here I have still confusing part. I have two very simple classes class DRect { private : double x0, y0, x1, y1; public : DRect(double a, double b, double c, double d) :...
2
by: Michael Bray | last post by:
With the recent release of EF I've decided to dig into it a bit more than I did before... the question I'm specifically interested in, but haven't been able to find a resource to answer it is......
55
by: tonytech08 | last post by:
How valuable is it that class objects behave like built-in types? I appears that the whole "constructor doesn't return a value because they are called by the compiler" thing is to enable...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
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,...
0
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...
0
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,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

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.