473,387 Members | 1,892 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,387 software developers and data experts.

Trick to prevent conversion


(I'm simplifying this problem greaty in the following code but you get
the idea)

I have a class something like:

class Processor {
public:
unsigned GetCurrentProcess(void);
unsigned GetCurrentThread(void);

void DoSomethingWithProcess(unsigned process_id);
void DoSomethingWithThread(unsigned thread_id);
};

The function, GetCurrentProcess, returns an unsigned integer value
which represents a process.
The function, GetCurrentThread, returns an unsigned integer value
which represents a thread.

The problem is, that it's very easy to mistakenly take the value from
GetCurrentProcess and pass it as an argument to DoSomethingWithThread.
(I've done it already!). Therefore, I want two different types for these
identifiers, two types that can't convert to each other. At the moment I
have the following:

class Processor {
public:

struct ProcessHandle { unsigned i; };
struct ThreadHandle { unsigned i; };

ProcessHandle GetCurrentProcess(void);
ThreadHandle GetCurrentThread(void);

void DoSomethingWithProcess(ProcessHandle process_id);
void DoSomethingWithThread(ThreadHandle thread_id);
};

Of course, this does the trick. But I'm wondering if there's a more
elegant way of doing it? What other methods are there for making types
incompatible with each other?

(My actual code is far more complicated than this -- obviously I wouldn't
be very competant if I made such a stupid mistake in code as simple as
this).

--
Tomás Ó hÉilidhe
Jan 11 '08 #1
5 1448
Tomás Ó hÉilidhe wrote:
(I'm simplifying this problem greaty in the following code but you get
the idea)

I have a class something like:

class Processor {
public:
unsigned GetCurrentProcess(void);
unsigned GetCurrentThread(void);
If you can, perhaps you would get in the habit of omitting 'void'
for a function with no arguments. I know I'd appreciate it because
your code would be easier to read and understand.

Also, it seems that those functions should perhaps be 'const'. If
they don't change anything in 'Processor', of course.
>
void DoSomethingWithProcess(unsigned process_id);
void DoSomethingWithThread(unsigned thread_id);
};

The function, GetCurrentProcess, returns an unsigned integer value
which represents a process.
The function, GetCurrentThread, returns an unsigned integer value
which represents a thread.

The problem is, that it's very easy to mistakenly take the value from
GetCurrentProcess and pass it as an argument to DoSomethingWithThread.
(I've done it already!). Therefore, I want two different types for
these identifiers, two types that can't convert to each other. At the
moment I have the following:

class Processor {
public:

struct ProcessHandle { unsigned i; };
struct ThreadHandle { unsigned i; };

ProcessHandle GetCurrentProcess(void);
ThreadHandle GetCurrentThread(void);

void DoSomethingWithProcess(ProcessHandle process_id);
void DoSomethingWithThread(ThreadHandle thread_id);
};

Of course, this does the trick. But I'm wondering if there's a more
elegant way of doing it? What other methods are there for making types
incompatible with each other?
Enums.
(My actual code is far more complicated than this -- obviously I
wouldn't be very competant if I made such a stupid mistake in code as
simple as this).
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Jan 11 '08 #2
On 11 Jan, 19:18, "Tomás Ó hÉilidhe" <t...@lavabit.comwrote:
>
The problem is, that it's very easy to mistakenly take the value from
GetCurrentProcess and pass it as an argument to DoSomethingWithThread.
(I've done it already!). Therefore, I want two different types for these
identifiers, two types that can't convert to each other. At the moment I
have the following:

class Processor {
public:

* * struct ProcessHandle { unsigned i; };
* * struct ThreadHandle { unsigned i; };

* * ProcessHandle GetCurrentProcess(void);
* * ThreadHandle GetCurrentThread(void);

* * void DoSomethingWithProcess(ProcessHandle process_id);
* * void DoSomethingWithThread(ThreadHandle thread_id);

};

Of course, this does the trick. But I'm wondering if there's a more
elegant way of doing it? What other methods are there for making types
incompatible with each other?
I think this is a pretty good way of doing it. One way of making it
a bit more elegant/generic would be something like this
(warning - untested):

template <typename W, class TAGclass TypeWrapper {
W myWrapped;
public:
explicit TypeWrapper(W wrapped) : myWrapped(wrapped) {}
W getWrapped() { return myWrapped; }
};

#define TYPE_WRAPPER(W, X) \
struct X##Tag{}; \
typedef TypeWrapper<W, X##TagX

This could be in a generic header file, then you could say:
// define types ...
TYPE_WRAPPER(unsigned, ProcessHandle);
TYPE_WRAPPER(unsigned, ThreadHandle);

// use them
ProcessHandle ph(some_unsigned_var);
unsigned x = ph.getWrapped();
// etc but
ThreadHandle th = ph; // fails to compile

Jan 11 '08 #3
tragomaskhalos <da*************@logicacmg.comwrote in news:b3fd120e-
46*************************@k2g2000h...legroup s.com:
I think this is a pretty good way of doing it. One way of making it
a bit more elegant/generic would be something like this
(warning - untested):

template <typename W, class TAGclass TypeWrapper {
W myWrapped;
public:
explicit TypeWrapper(W wrapped) : myWrapped(wrapped) {}
W getWrapped() { return myWrapped; }
};

#define TYPE_WRAPPER(W, X) \
struct X##Tag{}; \
typedef TypeWrapper<W, X##TagX

This could be in a generic header file, then you could say:
// define types ...
TYPE_WRAPPER(unsigned, ProcessHandle);
TYPE_WRAPPER(unsigned, ThreadHandle);

// use them
ProcessHandle ph(some_unsigned_var);
unsigned x = ph.getWrapped();
// etc but
ThreadHandle th = ph;

Honestly I think that's a bit much. Firstly, I'd want the type to remain
a POD, so constructors and private data are out the window. Also I
wouldn't want member functions coming into it.

I think I was right on track with my struct solution.
--
Tomás Ó hÉilidhe
Jan 11 '08 #4
On Fri, 11 Jan 2008 19:18:05 GMT, "Tomás Ó hÉilidhe" <to*@lavabit.com>
wrote in comp.lang.c++:
>
(I'm simplifying this problem greaty in the following code but you get
the idea)

I have a class something like:

class Processor {
public:
unsigned GetCurrentProcess(void);
unsigned GetCurrentThread(void);

void DoSomethingWithProcess(unsigned process_id);
void DoSomethingWithThread(unsigned thread_id);
};

The function, GetCurrentProcess, returns an unsigned integer value
which represents a process.
The function, GetCurrentThread, returns an unsigned integer value
which represents a thread.

The problem is, that it's very easy to mistakenly take the value from
GetCurrentProcess and pass it as an argument to DoSomethingWithThread.
(I've done it already!). Therefore, I want two different types for these
identifiers, two types that can't convert to each other. At the moment I
have the following:

class Processor {
public:

struct ProcessHandle { unsigned i; };
struct ThreadHandle { unsigned i; };

ProcessHandle GetCurrentProcess(void);
ThreadHandle GetCurrentThread(void);

void DoSomethingWithProcess(ProcessHandle process_id);
void DoSomethingWithThread(ThreadHandle thread_id);
};

Of course, this does the trick. But I'm wondering if there's a more
elegant way of doing it? What other methods are there for making types
incompatible with each other?

(My actual code is far more complicated than this -- obviously I wouldn't
be very competant if I made such a stupid mistake in code as simple as
this).
Why not two enumeration types, suitably defined so that hold the value
range you want, i.e.:

enum process_id { process_id_min = 0, process_id_max = UINT_MAX };
enum thread_id { thread_id_min = 0, process_id_max = UINT_MAX };

Modify your functions to accept and receive the enumerated types, with
suitable static_casts to and from unsigned int, as needed, inside the
functions, invisible to the caller. Modify your callers who get the
values to accept the appropriate enumeration type.

A C++ compiler will reject code where a caller retrieves a process_id
from one function and attempts to pass it to another that needs a
thread_id.

I even use this technique in C, where any decent compiler will warn
about mixing different enumeration types even though the language
permits it.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.club.cc.cmu.edu/~ajo/docs/FAQ-acllc.html
Jan 12 '08 #5
=?UTF-8?B?RXJpayBXaWtzdHLDtm0=?= <Er***********@telia.comwrote in
news:5c*****************@newsb.telia.net:
IF you do not want them to be mixed up you must use different types
for them, creating new types are done using class, struct, or enum. An
alternative is to use run-time checks, so instead of using indexes you
use handles (which could be unsigned ints) where each handles value is
some reversible function of both the type and the index, something
like:

unsigned getThreadHandle(unsigned index);
unsigned getThreadIndex(unsigned handle);

And if you pass a non-thread handle to getThreadIndex an exception is
thrown.

Only problem is that 3 could be a valid value for both an index and a
handle.

So far I'm still sticking with the simple struct method.

--
Tomás Ó hÉilidhe
Jan 12 '08 #6

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

Similar topics

10
by: Mac | last post by:
Is there a way to mimic the behaviour of C/C++'s preprocessor for macros? The problem: a lot of code like this: def foo(): # .... do some stuff if debug: emit_dbg_obj(DbgObjFoo(a,b,c)) #...
134
by: Joseph Garvin | last post by:
As someone who learned C first, when I came to Python everytime I read about a new feature it was like, "Whoa! I can do that?!" Slicing, dir(), getattr/setattr, the % operator, all of this was very...
17
by: Eternally | last post by:
Hey folks, I'm writing a simple C++ application which runs continuously. I'm running the program from the command line in Cygwin from XP, and it's cross-compatible with Linux. While running...
7
by: Philippe Guglielmetti | last post by:
I spent hours chasing a stupid bug of this kind: std::string bad='x'+"yz"; // results in anything except "xyz" ("yz" was in fact returned by some class::operator char*() conversion...) Any...
11
by: Steve Gough | last post by:
Could anyone please help me to understand what is happening here? The commented line produces an error, which is what I expected given that there is no conversion defined from type double to type...
6
by: Divya | last post by:
Hi, I have a web page which generates a CSV file based on some user input. When this file is downloaded by the user, the file is being automatically converted to .xls. Any idea how I can prevent...
0
by: Jon Paal | last post by:
text entered as ascii in a text box as "•" is converted to "&amp;#149;" how do I stop the conversion of the ampersand ?
6
by: YUS | last post by:
Hi, I've got a problem. I have a program that ask for a number to the user. If the user put a letter instead of a number the program crashes (loop). How can I prevent this ? I've tried with...
21
by: array7 | last post by:
I have been reading a lot of archived threads about "page-break- inside: avoid" not supported by IE5, IE6 IE55, IE7 and Firefox (Mozilla), which creates a really unpleasant-looking printout with...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
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$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
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...

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.