Topic: hey! proposal for new language features
Author: "Joe Borkoles" <undertoad@btinternet.com>
Date: Mon, 30 Jul 2001 18:02:44 GMT Raw View
"Marco Manfredini" <marco@technoboredom.net> wrote in message
news:Xns90ECD1AA3ED39marcotechnobore@technoboredom.net...
> "Joe Borkoles" <undertoad@btinternet.com> wrote in
> news:9jjae3$v9$1@neptunium.btinternet.com:
>
> >> > For example I can overload new()/delete() and new[]/delete[] BUT
> >> > I can't find out what class invoked the call - now we have RTTI
> >> > this seems like a nice idea.
> >>
> >> Class don't invoke operator new (or delete). Only a new-expression
> >> (delete-expression) invokes operator new (delete).
> >>
> >> You can put an operator new and delete into a class. They will
> >> be invoked for allocating or deallocating objects of that class
> >> type or derived class types.
> >>
> >> class C {
> >> public:
> >> void* operator new(size_t); // only for C or derived
> >> class void operator delete(void*); // ditto ...
> >> };
> >>
> >
> > Typically my systems may have between 20 and 150 classes, I can not
> > be expected to define new for each class. In addition it would only
> > be a partial solution, I wish to catch ALL newed memory and record
> > the class or type primitive that requested it. Using new/delete for
> > a class would only solve half the problem, not catchin new int;
> > etc.
> >
>
> // constructs a T, T is known to the allocator.
> template<class T>
> class New
> {
> T *result;
> void dump() { cout << "created a " << typeid(T).name() << " at " <<
> result << endl; }
> New() { result=T; dump(); }
> template<class A>
> New(const A &a) { result=new T(a); dump();}
> New(const A &a, const B &b) { result new T(a,b); dump();}
> // etc.
> operator T* () const { return result; }
> };
>
> int main()
> {
> string *s=New<string>("Hello");
> }
>
> But you really *want* new string("Hallo") to be changed, don't you?
>
My goodness me NO! Why would I want that. Look Steve has already probed a
bit about this. I DO NOT WANT TO CHANGE THE CURRENT SYNTAX OF THE NEW CALL
IN ANY C++ PROGRAMS.
I want access, inside the new() function, (and without having to write
specialised calls to some non standard memory allocation function) to the
fact that in your line above the class 'string' is requesting the newed
memory.
And I would like to point out that I believe most compilers have a hidden
API to do this already! They are used by memory leak detection programs.
> --
> Marco
>
> "Chapter 25 deals with the generalized subroutines for automatically
> transforming lemmings into gold."
>
lol
> ---
> [ comp.std.c++ is moderated. To submit articles, try just posting with ]
> [ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
> [ --- Please see the FAQ before posting. --- ]
> [ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
>
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "Neil A. Van Note" <vannote@netaxs.com>
Date: Thu, 2 Aug 2001 16:37:58 GMT Raw View
"Joe Borkoles" <undertoad@btinternet.com> wrote in message
news:9k46i5$fn4$1@neptunium.btinternet.com...
[SNIP]
> And I would like to point out that I believe most compilers have a hidden
> API to do this already! They are used by memory leak detection programs.
Sorry, there is no hidden API. BoundChecker and the like instrument your
compiled code to insert various runtime checks and hook your system calls
to perform parameter validation and more.
Best Regards
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "Joe Borkoles" <undertoad@btinternet.com>
Date: Sat, 28 Jul 2001 15:02:47 GMT Raw View
"Stephen Clamage" <stephen.clamage@sun.com> wrote in message
news:b0bvltka1cr56ibtb2frrhimb6om5ohkv4@4ax.com...
> On Tue, 24 Jul 2001 16:58:59 GMT, "Joe Borkoles"
> <undertoad@btinternet.com> wrote:
>
> >
> >"Steve Clamage" <clamage@eng.sun.com> wrote in message
> >news:Pine.SOL.3.96.1010723082557.23359C-100000@taumet...
> >> On Sun, 22 Jul 2001, Joe Borkoles wrote:
> >>
> >> > 1. open up / extend the memory allocation functions to allow, for
> >instance,
> >> > people to write their own memory allocation checkers.
> >> > -------------------------------------------------------
> >>
> >> Well, you can already do that, via at least two different mechanisms.
> >>
> >
> >I agree there are mechanisms, and that is all well and good. My point is
I
> >wish to be able to determine which class invoked the new call within the
> >standard global new function itself!
>
> But the whole point of the dichotomy between new-expression and the
> default memory allocator (global operator new) is that the allocator
> does not need to know anything about types. Its only purpose is to
> allocate raw memory. This is an application of the fundamental design
> principle of separation of concerns.
>
That is a good point, however I suggest that design constraints can change
and that new should provide access to the type that was involved in the
call. While what you say is correct, I feel that the very fact that the new
call is always associated with a type of some kind, either user defined (a
class) or primitive (eg long) is a dead give away that more might be
expected of it. i.e.
int* myint = new int(9);
MyClass* mc = new MyClass();
What I suggest does not involve making any kind of changes to existing well
formed C++ programs, or even current custom new functions in programs. I
merely state that as an experienced C++ developer I have had numerous
occasions to write a global new and have found that having access to the
class that the call was involved with inside new (and without having to
introduce unusual calling syntax for new) would be very very useful. Let me
repeat, this is a localised (suggested) change. It shouldn't afftect any
existing C++ programs in anyway.
> If for some reason you want the allocator to know about types, you can
> create one that knows about types, and use it in your code.
>
> >What you suggest is available and
> >compiles but involves me changing my source code so that it only works
with
> >new operators that take the new parameter.
>
> So instead are you suggesting the language design change so that
> everyone else's code is invalidated? If not, what are you suggesting?
>
see above.
To expand, the calling syntax should remain the same and the current new
function should still have the same signature. We are getting to the
specifics of how the proposal should work here, which I dont want to do
until the general principal is agreed upon. (see last comment)
> >
> >>
> >> > Also access to static initialisation stuff, perhaps something like
> >> > set_new_handler(),
> >> >
> >> > e.g.. set_static_init_handlers( void* pre_handler, void*
post_handler)
> >and
> >> > set_static_cleanup_handlers( ...
> >>
> >> You'll have to explain what problem you are trying to solve for
> >> which a good solution does not already exist.
> >>
> >> ---
> >
> >I am writing a simple memory checker for my c++ programs. I want to catch
> >leaks with a simple mechanism, currently what I have counts allocations
and
> >deletions and reports any mismatch. But if my programs have any
statically
> >allocated variables, and this breaks the code as new has already been
called
> >before my code gets a lookin (presumably by statics).
>
> You've lost me. By definition, static objects do not involve operator
> new. They are magically allocated at program start, typically by the
> object code linker or by the runtime program loader.
>
You know I agree, but the facts are that the Borland compiler when linking
with VCL has already done some memory allocation (45 I think) with new
before it calls my code. I have assumed that global static objects are
calling new themselves.
> You are allowed to replace the global operator new and delete. You can
> do that to keep track of allocations and deallocations to report
> leaks. That would be the case even for memory allocated by
> constructors of objects with static storage duration.
>
The thing about statics is that the code to create and clean them up is
called before main() and after main respectively. By providing this simple
facility I could ensure that my code was called before anyone elses
(including the compiler vendor). Again this stuff in no way affects any
existing programs, provides a facility that is not currently available, but
that I want to use, and can not be achieved in any other way.
Let me state that I think these suggested changes could be added to the
language very cheaply, and without any kind of invalidation of any existing
code being necessary. That is if we thought this was a sound idea then the
actual mechanism added to the language would in no way affect any existing
programs (well almost...there might be one program at Nepal University
passing in a pointer to the class's typeinfo..).
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: Sat, 28 Jul 2001 16:20:10 GMT Raw View
In article <9jueqn$5dp$1@neptunium.btinternet.com>, Joe Borkoles
<undertoad@btinternet.com> writes
>
>"Stephen Clamage" <stephen.clamage@sun.com> wrote in message
>news:b0bvltka1cr56ibtb2frrhimb6om5ohkv4@4ax.com...
>> On Tue, 24 Jul 2001 16:58:59 GMT, "Joe Borkoles"
>> <undertoad@btinternet.com> wrote:
>>
>> >
>> >"Steve Clamage" <clamage@eng.sun.com> wrote in message
>> >news:Pine.SOL.3.96.1010723082557.23359C-100000@taumet...
>> >> On Sun, 22 Jul 2001, Joe Borkoles wrote:
>> >>
>> >> > 1. open up / extend the memory allocation functions to allow, for
>> >instance,
>> >> > people to write their own memory allocation checkers.
>> >> > -------------------------------------------------------
>> >>
>> >> Well, you can already do that, via at least two different mechanisms.
>> >>
>> >
>> >I agree there are mechanisms, and that is all well and good. My point is
>I
>> >wish to be able to determine which class invoked the new call within the
>> >standard global new function itself!
>>
>> But the whole point of the dichotomy between new-expression and the
>> default memory allocator (global operator new) is that the allocator
>> does not need to know anything about types. Its only purpose is to
>> allocate raw memory. This is an application of the fundamental design
>> principle of separation of concerns.
>>
>
>That is a good point, however I suggest that design constraints can change
>and that new should provide access to the type that was involved in the
>call.
What type? The following is entirely correct and involves no type:
void * ptr = operator new(1000);
> While what you say is correct, I feel that the very fact that the new
>call is always associated with a type of some kind, either user defined (a
>class) or primitive (eg long) is a dead give away that more might be
>expected of it. i.e.
>
>int* myint = new int(9);
>
>MyClass* mc = new MyClass();
But you are confusing operator new with the new expression. The new
expression knows what type is involved but you have no access to that,
it is part of the core language and is not user modifiable/replaceable.
>
>What I suggest does not involve making any kind of changes to existing well
>formed C++ programs, or even current custom new functions in programs. I
>merely state that as an experienced C++ developer I have had numerous
>occasions to write a global new and have found that having access to the
>class that the call was involved with inside new (and without having to
>introduce unusual calling syntax for new) would be very very useful. Let me
>repeat, this is a localised (suggested) change. It shouldn't afftect any
>existing C++ programs in anyway.
It isn't, it is based on a fundamental confusion between the allocation
function you write and the new expression. What you suggest would
require a fundamental change to the language, not least you would be
changing the signature of the global operator new.
>
>> If for some reason you want the allocator to know about types, you can
>> create one that knows about types, and use it in your code.
>>
>> >What you suggest is available and
>> >compiles but involves me changing my source code so that it only works
>with
>> >new operators that take the new parameter.
>>
>> So instead are you suggesting the language design change so that
>> everyone else's code is invalidated? If not, what are you suggesting?
>>
>
>see above.
>
>To expand, the calling syntax should remain the same and the current new
>function should still have the same signature. We are getting to the
>specifics of how the proposal should work here, which I dont want to do
>until the general principal is agreed upon. (see last comment)
How can any sane person agree to a principle which seems so at variance
with the way the language was previously designed. With the change you
appear to want, how do you propose I allocate raw memory? (Yes, I know
about the C mechanism, but I normally use the C++ mechanism precisely
because I get the benefit of any fancy footwork being provided by
operator new.
>
>> >
>> >>
>> >> > Also access to static initialisation stuff, perhaps something like
>> >> > set_new_handler(),
>> >> >
>> >> > e.g.. set_static_init_handlers( void* pre_handler, void*
>post_handler)
>> >and
>> >> > set_static_cleanup_handlers( ...
>> >>
>> >> You'll have to explain what problem you are trying to solve for
>> >> which a good solution does not already exist.
>> >>
>> >> ---
>> >
>> >I am writing a simple memory checker for my c++ programs. I want to catch
>> >leaks with a simple mechanism, currently what I have counts allocations
>and
>> >deletions and reports any mismatch. But if my programs have any
>statically
>> >allocated variables, and this breaks the code as new has already been
>called
>> >before my code gets a lookin (presumably by statics).
>>
>> You've lost me. By definition, static objects do not involve operator
>> new. They are magically allocated at program start, typically by the
>> object code linker or by the runtime program loader.
>>
>
>You know I agree, but the facts are that the Borland compiler when linking
>with VCL has already done some memory allocation (45 I think) with new
>before it calls my code. I have assumed that global static objects are
>calling new themselves.
The compiler is explicitly not allowed to use operator new() other than
when it is called explicitly by the user or implicitly by the use of the
new expression. How the compiler provides memory for static objects is
its business but it must not be via a call to operator new.
>
>> You are allowed to replace the global operator new and delete. You can
>> do that to keep track of allocations and deallocations to report
>> leaks. That would be the case even for memory allocated by
>> constructors of objects with static storage duration.
>>
>
>The thing about statics is that the code to create and clean them up is
>called before main() and after main respectively. By providing this simple
>facility I could ensure that my code was called before anyone elses
>(including the compiler vendor). Again this stuff in no way affects any
>existing programs, provides a facility that is not currently available, but
>that I want to use, and can not be achieved in any other way.
??? Now you have completely lost me. What if two people attempt what you
are proposing? Who wins?
>
>Let me state that I think these suggested changes could be added to the
>language very cheaply, and without any kind of invalidation of any existing
>code being necessary. That is if we thought this was a sound idea then the
>actual mechanism added to the language would in no way affect any existing
>programs (well almost...there might be one program at Nepal University
>passing in a pointer to the class's typeinfo..).
Asserting something does not make it true.
Francis Glassborow ACCU
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: marco@technoboredom.net (Marco Manfredini)
Date: Sat, 28 Jul 2001 19:23:20 GMT Raw View
"Joe Borkoles" <undertoad@btinternet.com> wrote in
news:9jjae3$v9$1@neptunium.btinternet.com:
>> > For example I can overload new()/delete() and new[]/delete[] BUT
>> > I can't find out what class invoked the call - now we have RTTI
>> > this seems like a nice idea.
>>
>> Class don't invoke operator new (or delete). Only a new-expression
>> (delete-expression) invokes operator new (delete).
>>
>> You can put an operator new and delete into a class. They will
>> be invoked for allocating or deallocating objects of that class
>> type or derived class types.
>>
>> class C {
>> public:
>> void* operator new(size_t); // only for C or derived
>> class void operator delete(void*); // ditto ...
>> };
>>
>
> Typically my systems may have between 20 and 150 classes, I can not
> be expected to define new for each class. In addition it would only
> be a partial solution, I wish to catch ALL newed memory and record
> the class or type primitive that requested it. Using new/delete for
> a class would only solve half the problem, not catchin new int;
> etc.
>
// constructs a T, T is known to the allocator.
template<class T>
class New
{
T *result;
void dump() { cout << "created a " << typeid(T).name() << " at " <<
result << endl; }
New() { result=T; dump(); }
template<class A>
New(const A &a) { result=new T(a); dump();}
New(const A &a, const B &b) { result new T(a,b); dump();}
// etc.
operator T* () const { return result; }
};
int main()
{
string *s=New<string>("Hello");
}
But you really *want* new string("Hallo") to be changed, don't you?
--
Marco
"Chapter 25 deals with the generalized subroutines for automatically
transforming lemmings into gold."
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "Sef Campstein" <sef@campst.tmfweb.nl>
Date: Wed, 25 Jul 2001 17:38:01 GMT Raw View
Why not implement it using current C++?
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: Noah Stein <noah@vision-scape.com>
Date: Wed, 25 Jul 2001 17:38:01 GMT Raw View
Well, I decided to make a template version of the code to see the facets of
a template version of the set. The code isn't 100% robust; however, all
major aspects have been implemented (I believe). Here's the code for the
generic set functionality:
template<class Cfg> class Elements
{
typedef typename Cfg::val_type V;
typedef typename Cfg::domain D;
V val;
Elements(const V v) : val(v) {}
public:
Elements(const D v) : val(v) {}
operator V() const
{ return val; }
Elements<Cfg> operator +(const D rhs)
{ return Elements<Cfg>(val+static_cast<V>(rhs)); }
};
template<class Cfg> class Set
{
typedef typename Cfg::val_type V;
V val;
public:
Set() : val(0) {}
Set(const Elements<Cfg> e) : val(static_cast<V>(e)) {}
operator V() const
{ return val; }
Set<Cfg>& operator+=(const Elements<Cfg> rhs)
{ val |=static_cast<V>(rhs); return *this; }
Set<Cfg>& operator-=(const Elements<Cfg> rhs)
{ val&=~static_cast<V>(rhs); return *this; }
Set<Cfg>& operator=(const Elements<Cfg> rhs)
{ val = static_cast<V>(rhs); return *this; }
};
#define SetOps(Cfg) \
Elements<Cfg> operator+(const Cfg::domain lhs, const Cfg::domain rhs) \
{ \
typedef Cfg::domain D; \
typedef Cfg::val_type V; \
return
Elements<Cfg>(static_cast<D>(static_cast<V>(lhs)|static_cast<V>(rhs))); \
}
/***************************/
An example usage:
/*enum Style { Child = 1, Border = 2, Parent = 4 };*/
struct WS
{
enum domain { Child = 1, Border = 2, Parent = 4 };
/*typedef Style domain;*/
typedef DWORD val_type;
};
SetOps(WS)
typedef Set<WS> WindowStyle;
WindowStyle s2(WS::Child);
WindowStyle s3(WS::Child+WS::Border+WS::Parent);
/*s2+= 7;*/
s3 -= WS::Border;
s2 += WS::Parent;
s2 = WS::Border+WS::Parent;
WindowStyle s4 = WS::Border+WS::Parent;
DWORD se = s3;
/*************************/
The first two commented lines in the example illustrate two separate methods
for defining the set of flags. The uncommented code has Child, Parent, and
Border defined locally to the traits struct. This ends up with a notation
that almost looks like the original Win32 defines. If the commented
versions are used instead, the enum ends up being globally defined, and it
looks like the initial example. I only state this to show that it can work
as specified in the example.
The SetOps macro is essentially, although not technically, required. Any
concatenation of multiple flags requires a global operator since the two
operands are both enums. I could avoid this step; however, I would have to
use a class instead of the enum, and the system would end up being a little
heavier than requiring the use of the macro.
All told, this generic set implementation requires only a small amount of
effort to define each set: a struct with two elements defined (the allowable
values and the conversion type), and an invocation of one macro with the
name of the struct.
-- Noah
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "Daniel Pfeffer" <daniel.pfeffer@storlogic.co.il>
Date: Wed, 25 Jul 2001 21:05:46 GMT Raw View
"Joe Borkoles" <undertoad@btinternet.com> wrote in message
news:9jj8q6$s09$1@neptunium.btinternet.com...
>
> "Marco Manfredini" <marco@technoboredom.net> wrote in message
> news:Xns90E74097252Fmarcotechnobore@technoboredom.net...
> > "Joe Borkoles" <undertoad@btinternet.com> wrote in
> > news:9jehpu$huv$1@uranium.btinternet.com:
> >
> >
> > a) you suggest to define the set of WindowStyles as bitset<32>, so how
> > is the compiler supposed to know, that only WindowStyles can make it
> > into _styles?
>
> Wait that is what I am saying!
>
> There is no way to define a set of enum like values to use as bitfields
and
> have the COMPILER check that ONLY the flags you wish are put into the set.
> You dont seem familiar with the style of programming so I'll reveal my
> shameful secret I am a Win32 programmer, since I was able to drool on my
> daddy's lap, and this stuff is used extensively. As it is so widely used
in
> Win32 and as Win32 is such a dominate programming paradigm I felt full
> language support for this feature would be a good thing. All I know is I
> have been writing programs for Solaris and Win32 for over 15 yrs in C++
and
> I want this feature a lot.
>
> Also the bitset example is directly taken from Plauger book on the C++
> library, it is the recomended way of doing what I suggest.(My edition is a
> little old and he talks about <bits> instead of <bitset> but I am sure the
> latest edition gives the same example).
>
> So we agree (kind of). The compiler doesn't support defining a set of
> bitmask values for a bitset type! Ok!
>
> >
> > b) "style |= Child | FatBorder;" is mathematically, logically or
> > whateverly nonsense. "Child" and "FarBorder" are *not* sets (they are
> > enumerated Elements), so there cannot be an union operation between
> > them. (this only works, when the enum members are defined to match bit
> > positions, which means that they are treated as single-element sets)
> >
>
> No, no no! These are BITMASKS, and WindowStyle is a BITFIELD, the code is
> (almost) actual code in daily usage on EVERY Windows system since Windows
> 2.0 for me.
>
> WindowStyle style = Parent;
> style |= Child | FatBorder;
>
> means.. the variable 'stye' has its current value (Parent), ORed with the
> ORed result of Child and FatBorder. This code compiles right now, given
the
> bitset<> definitions of the original article or the usage that we have
today
> of using longs and #defines (again just check our ::CreateWindowEx() and
> windows.h for say WS_CHILD | WS_BORDER to see popular usage today). To be
> even more explicit, if Parent = 0x1, Child=0x2 and FatBorder=0x4, style
> would contain 0x7!
>
> I have personally replaced the #defines Windows uses with enums in my own
> code, but I have to suppress a compiler warning as the compiler doesn't
> really like my way of using enums as bitfields. ie
>
> enum WindowsStyle { Child=WS_CHILD, Parent=WS_PARENT, Border=WS_BORDER );
> (etc.)
>
> where WS_CHILD is a #define from <windows.h>, this code is in daily use in
> my stuff.
>
> > Here is the Obvious Sample(tm) for what you want:
> >
> > #include <iostream>
> > using namespace std;
> >
> > enum Flags { Read, Write, Share };
> >
> > template<class T>
> > struct SetOf
> > {
> > struct BoolRef
> > {
> > SetOf<T> &set;
> > T fl;
> > operator bool () { return set.hasMember(fl); };
> > BoolRef & operator=(bool b)
> > {
> > if (b) set<<fl; else set>>fl;
> > return *this;
> > }
> > BoolRef(SetOf<T>&_set, T _fl) : set(_set), fl(_fl) {}
> > };
> > unsigned values;
> > SetOf& operator << (T fl)
> > {
> > values |= (1<<fl);
> > return *this;
> > }
> > SetOf operator >> (T fl)
> > {
> > values &= ~(1<<fl);
> > return *this;
> > }
> > boolRef operator ->* (T fl)
> > {
> > return BoolRef(*this, fl);
> > }
> > bool hasMember(T fl)
> > {
> > return (0!=(values & (1<<fl)));
> > }
> > };
> >
> > int main()
> > {
> > SetOf<Flags> f;
> > f<<Read <<Write >>Share ; // set read, write, but not share
> > cout << f->*Write << f->*Read << f->*Share << endl;
> > f>>Read; // unset read
> > f->*Share=true; // set Share
> > cout << f->*Write << f->*Read << f->*Share << endl;
> > }
> >
>
> With respect, I suggest that the above code is too long and verbose and I
am
> suggesting replacing it with 2 lines of code:
>
> bitfield WindowStyle { Child, Border, Parent, FatBorder };
> WindowStyle ws = Child | Border;
>
> Now this is itself a compelling reason to adopt my suggestion, your code
may
> work, but it is hardly as readable as my 2 lines are. And to be honest the
> usage we have right now in Windows is hardly likely to be replaced by your
> code as it is much longer to type (Windows programmers are notoriously
lazy)
> and is less succinct.. The code I suggest is even more succinct and
compact
> than current code, far far less error prone and checked by the compiler.
>
> Let me just try to rejustify my (HONEST) request for a new feature!
> Seriously all Windows programmers use this bitfields stuff everyday and
> there is no support for it in the compiler. Every single Window has a set
of
> unique winow styles, radio buttons, edit boxes, trees, everything. And
since
> I started using Windows years ago I have had more than one occassion to
use
> this bitfield concept for a kind of style on my own classes (I suggest
that
> it is in fact a idiom - al la Copland). I am saying that a very poor,
error
> prone alternative is in use daily by programmers, and that this simple and
> clear addition would make one more aspect of large complex programs for
> Windows verifiable by compiler, and that further it wouldn't compilcate
the
> language syntax and is in fact a 'cheap' addition.
While your concept is useful, I believe that it should not make it into the
language or the Standard library. You could just as easily write a class to
set bits, as follows:
class WindowsBitField {
public:
WindowsBitField() : value_(0) {}
enum WindowsStyles {Style1, Style2,Style3...};
BitField &operator |=(WindowsStyles n) { value_ |= (1lu << n);
return *this; }
BitField &operator &=(WindowsStyles n) { value_ &= ~(1lu << n);
return *this; }
/* other useful operations omitted */
unsigned long value() const { return value_; }
private:
unsigned long value_;
};
Daniel Pfeffer
======================================= MODERATOR'S COMMENT:
Please don't overquote.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: Stephen Clamage <stephen.clamage@sun.com>
Date: Thu, 26 Jul 2001 06:04:14 GMT Raw View
On Tue, 24 Jul 2001 16:58:59 GMT, "Joe Borkoles"
<undertoad@btinternet.com> wrote:
>
>"Steve Clamage" <clamage@eng.sun.com> wrote in message
>news:Pine.SOL.3.96.1010723082557.23359C-100000@taumet...
>> On Sun, 22 Jul 2001, Joe Borkoles wrote:
>>
>> > 1. open up / extend the memory allocation functions to allow, for
>instance,
>> > people to write their own memory allocation checkers.
>> > -------------------------------------------------------
>>
>> Well, you can already do that, via at least two different mechanisms.
>>
>
>I agree there are mechanisms, and that is all well and good. My point is I
>wish to be able to determine which class invoked the new call within the
>standard global new function itself!
But the whole point of the dichotomy between new-expression and the
default memory allocator (global operator new) is that the allocator
does not need to know anything about types. Its only purpose is to
allocate raw memory. This is an application of the fundamental design
principle of separation of concerns.
If for some reason you want the allocator to know about types, you can
create one that knows about types, and use it in your code.
>What you suggest is available and
>compiles but involves me changing my source code so that it only works with
>new operators that take the new parameter.
So instead are you suggesting the language design change so that
everyone else's code is invalidated? If not, what are you suggesting?
>
>>
>> > Also access to static initialisation stuff, perhaps something like
>> > set_new_handler(),
>> >
>> > e.g.. set_static_init_handlers( void* pre_handler, void* post_handler)
>and
>> > set_static_cleanup_handlers( ...
>>
>> You'll have to explain what problem you are trying to solve for
>> which a good solution does not already exist.
>>
>> ---
>
>I am writing a simple memory checker for my c++ programs. I want to catch
>leaks with a simple mechanism, currently what I have counts allocations and
>deletions and reports any mismatch. But if my programs have any statically
>allocated variables, and this breaks the code as new has already been called
>before my code gets a lookin (presumably by statics).
You've lost me. By definition, static objects do not involve operator
new. They are magically allocated at program start, typically by the
object code linker or by the runtime program loader.
You are allowed to replace the global operator new and delete. You can
do that to keep track of allocations and deallocations to report
leaks. That would be the case even for memory allocated by
constructors of objects with static storage duration.
Indeed, many products are available that already do this for you by
the simple expedient of replacing the global new and delete.
So I still don't see why you think a language change is necessary.
---
Steve Clamage, stephen.clamage@sun.com
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "Joe Borkoles" <undertoad@btinternet.com>
Date: Tue, 24 Jul 2001 09:50:37 GMT Raw View
"Marco Manfredini" <marco@technoboredom.net> wrote in message
news:Xns90E74097252Fmarcotechnobore@technoboredom.net...
> "Joe Borkoles" <undertoad@btinternet.com> wrote in
> news:9jehpu$huv$1@uranium.btinternet.com:
>
>
> a) you suggest to define the set of WindowStyles as bitset<32>, so how
> is the compiler supposed to know, that only WindowStyles can make it
> into _styles?
Wait that is what I am saying!
There is no way to define a set of enum like values to use as bitfields and
have the COMPILER check that ONLY the flags you wish are put into the set.
You dont seem familiar with the style of programming so I'll reveal my
shameful secret I am a Win32 programmer, since I was able to drool on my
daddy's lap, and this stuff is used extensively. As it is so widely used in
Win32 and as Win32 is such a dominate programming paradigm I felt full
language support for this feature would be a good thing. All I know is I
have been writing programs for Solaris and Win32 for over 15 yrs in C++ and
I want this feature a lot.
Also the bitset example is directly taken from Plauger book on the C++
library, it is the recomended way of doing what I suggest.(My edition is a
little old and he talks about <bits> instead of <bitset> but I am sure the
latest edition gives the same example).
So we agree (kind of). The compiler doesn't support defining a set of
bitmask values for a bitset type! Ok!
>
> b) "style |= Child | FatBorder;" is mathematically, logically or
> whateverly nonsense. "Child" and "FarBorder" are *not* sets (they are
> enumerated Elements), so there cannot be an union operation between
> them. (this only works, when the enum members are defined to match bit
> positions, which means that they are treated as single-element sets)
>
No, no no! These are BITMASKS, and WindowStyle is a BITFIELD, the code is
(almost) actual code in daily usage on EVERY Windows system since Windows
2.0 for me.
WindowStyle style = Parent;
style |= Child | FatBorder;
means.. the variable 'stye' has its current value (Parent), ORed with the
ORed result of Child and FatBorder. This code compiles right now, given the
bitset<> definitions of the original article or the usage that we have today
of using longs and #defines (again just check our ::CreateWindowEx() and
windows.h for say WS_CHILD | WS_BORDER to see popular usage today). To be
even more explicit, if Parent = 0x1, Child=0x2 and FatBorder=0x4, style
would contain 0x7!
I have personally replaced the #defines Windows uses with enums in my own
code, but I have to suppress a compiler warning as the compiler doesn't
really like my way of using enums as bitfields. ie
enum WindowsStyle { Child=WS_CHILD, Parent=WS_PARENT, Border=WS_BORDER );
(etc.)
where WS_CHILD is a #define from <windows.h>, this code is in daily use in
my stuff.
> Here is the Obvious Sample(tm) for what you want:
>
> #include <iostream>
> using namespace std;
>
> enum Flags { Read, Write, Share };
>
> template<class T>
> struct SetOf
> {
> struct BoolRef
> {
> SetOf<T> &set;
> T fl;
> operator bool () { return set.hasMember(fl); };
> BoolRef & operator=(bool b)
> {
> if (b) set<<fl; else set>>fl;
> return *this;
> }
> BoolRef(SetOf<T>&_set, T _fl) : set(_set), fl(_fl) {}
> };
> unsigned values;
> SetOf& operator << (T fl)
> {
> values |= (1<<fl);
> return *this;
> }
> SetOf operator >> (T fl)
> {
> values &= ~(1<<fl);
> return *this;
> }
> boolRef operator ->* (T fl)
> {
> return BoolRef(*this, fl);
> }
> bool hasMember(T fl)
> {
> return (0!=(values & (1<<fl)));
> }
> };
>
> int main()
> {
> SetOf<Flags> f;
> f<<Read <<Write >>Share ; // set read, write, but not share
> cout << f->*Write << f->*Read << f->*Share << endl;
> f>>Read; // unset read
> f->*Share=true; // set Share
> cout << f->*Write << f->*Read << f->*Share << endl;
> }
>
With respect, I suggest that the above code is too long and verbose and I am
suggesting replacing it with 2 lines of code:
bitfield WindowStyle { Child, Border, Parent, FatBorder };
WindowStyle ws = Child | Border;
Now this is itself a compelling reason to adopt my suggestion, your code may
work, but it is hardly as readable as my 2 lines are. And to be honest the
usage we have right now in Windows is hardly likely to be replaced by your
code as it is much longer to type (Windows programmers are notoriously lazy)
and is less succinct.. The code I suggest is even more succinct and compact
than current code, far far less error prone and checked by the compiler.
Let me just try to rejustify my (HONEST) request for a new feature!
Seriously all Windows programmers use this bitfields stuff everyday and
there is no support for it in the compiler. Every single Window has a set of
unique winow styles, radio buttons, edit boxes, trees, everything. And since
I started using Windows years ago I have had more than one occassion to use
this bitfield concept for a kind of style on my own classes (I suggest that
it is in fact a idiom - al la Copland). I am saying that a very poor, error
prone alternative is in use daily by programmers, and that this simple and
clear addition would make one more aspect of large complex programs for
Windows verifiable by compiler, and that further it wouldn't compilcate the
language syntax and is in fact a 'cheap' addition.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "Joe Borkoles" <undertoad@btinternet.com>
Date: Tue, 24 Jul 2001 16:58:59 GMT Raw View
"Steve Clamage" <clamage@eng.sun.com> wrote in message
news:Pine.SOL.3.96.1010723082557.23359C-100000@taumet...
> On Sun, 22 Jul 2001, Joe Borkoles wrote:
>
> > 1. open up / extend the memory allocation functions to allow, for
instance,
> > people to write their own memory allocation checkers.
> > -------------------------------------------------------
>
> Well, you can already do that, via at least two different mechanisms.
>
I agree there are mechanisms, and that is all well and good. My point is I
wish to be able to determine which class invoked the new call within the
standard global new function itself! What you suggest is available and
compiles but involves me changing my source code so that it only works with
new operators that take the new parameter.
I suggest that the type of the class new is invoked on be available within
the standard array and non array global new and delete.
After all if I new some memoy it is always associated with a type!
int* arrayOfInts = new int[20];
or
MyClass* arrayOfMyClass = new MyClass[20];
and so on, so from the usage point of view the caller always specifies a
class (or type primitive) when invoking new.
> > For example I can overload new()/delete() and new[]/delete[] BUT I can't
> > find out what class invoked the call - now we have RTTI this seems like
a
> > nice idea.
>
> Class don't invoke operator new (or delete). Only a new-expression
> (delete-expression) invokes operator new (delete).
>
> You can put an operator new and delete into a class. They will
> be invoked for allocating or deallocating objects of that class
> type or derived class types.
>
> class C {
> public:
> void* operator new(size_t); // only for C or derived class
> void operator delete(void*); // ditto
> ...
> };
>
Typically my systems may have between 20 and 150 classes, I can not be
expected to define new for each class. In addition it would only be a
partial solution, I wish to catch ALL newed memory and record the class or
type primitive that requested it. Using new/delete for a class would only
solve half the problem, not catchin new int; etc.
> You can create a "placement" version of operator new that takes
> addtional parameters, which could be (for example) RTTI data for
> the type of the object being created.
>
> void* operator new(size_t, const std::type_info&); // placement new
> C* p = new (typeid(C)) C; // use placement new
>
see first comment (I think!).
>
> > Also access to static initialisation stuff, perhaps something like
> > set_new_handler(),
> >
> > e.g.. set_static_init_handlers( void* pre_handler, void* post_handler)
and
> > set_static_cleanup_handlers( ...
>
> You'll have to explain what problem you are trying to solve for
> which a good solution does not already exist.
>
> ---
I am writing a simple memory checker for my c++ programs. I want to catch
leaks with a simple mechanism, currently what I have counts allocations and
deletions and reports any mismatch. But if my programs have any statically
allocated variables, and this breaks the code as new has already been called
before my code gets a lookin (presumably by statics). I simply want to have
a function called before and after statics are allocated by the compiler and
cleanedup by the compiler. ie the static init pre_handler above would be
guaranteed to be called BEFORE any memory was allocated ANYWHERE in the C++
program.
Again to rejustify my request, I suggest that we need this because compiler
vendors ALREADY secretly provide this information, or so I assume, in order
to allow the memory checking tools we have today. If the function call uses
the information (ie the class is always specified when new() is invoked) and
compiler vendors provide this kind of functionality anyway, all I suggest is
making it available to everyone, I know I have wanted to use it more than a
couple of times during my programs.
Also I would, given the above, write a memory profiler!
Further I suggest that as C++ gets used to write larger and larger systems
the memory allocation routines may become of increasing importance to the
project, perhaps even requiring a developer for customised memory allocation
on a project! And that this is the FIRST step to providing the required
memory allocation features that larger more sophisticated, as yet undreamed
of projects will require. (And wouldn't it be nice to be ahead of the
requirements for the language instead of always trailing!)
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: marco@technoboredom.net (Marco Manfredini)
Date: Tue, 24 Jul 2001 17:01:37 GMT Raw View
"Joe Borkoles" <undertoad@btinternet.com> wrote in
news:9jj8q6$s09$1@neptunium.btinternet.com:
>
> "Marco Manfredini" <marco@technoboredom.net> wrote in message
> news:Xns90E74097252Fmarcotechnobore@technoboredom.net...
>>
>> b) "style |= Child | FatBorder;" is mathematically, logically or
>> whateverly nonsense. "Child" and "FarBorder" are *not* sets (they
>> are enumerated Elements), so there cannot be an union operation
>> between them. (this only works, when the enum members are defined
>> to match bit positions, which means that they are treated as
>> single-element sets)
>>
>
> No, no no! These are BITMASKS, and WindowStyle is a BITFIELD, the
> code is (almost) actual code in daily usage on EVERY Windows system
> since Windows 2.0 for me.
>
> WindowStyle style = Parent;
> style |= Child | FatBorder;
>
> means.. the variable 'stye' has its current value (Parent), ORed
> with the ORed result of Child and FatBorder. This code compiles
> right now, given the bitset<> definitions of the original article
> or the usage that we have today of using longs and #defines (again
> just check our ::CreateWindowEx() and windows.h for say WS_CHILD |
> WS_BORDER to see popular usage today). To be even more explicit, if
> Parent = 0x1, Child=0x2 and FatBorder=0x4, style would contain 0x7!
The Windows API (and mostly the USER and GDI Part) has more serious
problems than its flags. Just to mention a few: It does not port to a
big-endian architecture (See this MSDN Knowledgebase Entry: Q102025),
The ownership of objects is mysterious (a DC can be freed with
ReleaseDC, DestroyDC or EndPaint depending on where you have it from,
and you have to remember which brushes, pens etc. it uses), the headers
define too many macros (winnt.h defines a value named DELETE!! DELETE
what? for what DELETE??).
>> Here is the Obvious Sample(tm) for what you want:
[snip]
> With respect, I suggest that the above code is too long and verbose
> and I am suggesting replacing it with 2 lines of code:
>
> bitfield WindowStyle { Child, Border, Parent, FatBorder };
> WindowStyle ws = Child | Border;
>
> Now this is itself a compelling reason to adopt my suggestion, your
> code may work, but it is hardly as readable as my 2 lines are. And
> to be honest the usage we have right now in Windows is hardly
> likely to be replaced by your code as it is much longer to type
> (Windows programmers are notoriously lazy) and is less succinct..
> The code I suggest is even more succinct and compact than current
> code, far far less error prone and checked by the compiler.
>
What you have to type is:
enum WindowStyle { Child, Border, Parent, FatBorder };
SetOf<WindowStyle> ws; ws<<Child<<Border;
The SetOf declaration is part of your framework. You'll have to type it
once only. Is definitley working and what you do is checked by the
compiler. (And btw. if Windows programmers are notoriously lazy, they
should use templates more)
> Let me just try to rejustify my (HONEST) request for a new feature!
> Seriously all Windows programmers use this bitfields stuff everyday
> and there is no support for it in the compiler. Every single Window
> has a set of unique winow styles, radio buttons, edit boxes, trees,
I don't think, that the concept of "set" is a secret that has only be
revealed to windows programmers. Just for an example, Pascal had what I
described built into the language:
TYPE
StyleElements = (Child, Border, Parent, FatBorder);
WindowStyle = SET OF StyleElements;
and AFAIK most procedural languages have this kind of stuff. C++ does
not have it built in, but is powerful enough to implement it (in a
typesafe way!) in its own terms.
> everything. And since I started using Windows years ago I have had
> more than one occassion to use this bitfield concept for a kind of
> style on my own classes (I suggest that it is in fact a idiom - al
> la Copland). I am saying that a very poor, error prone alternative
> is in use daily by programmers, and that this simple and clear
> addition would make one more aspect of large complex programs for
> Windows verifiable by compiler, and that further it wouldn't
> compilcate the language syntax and is in fact a 'cheap' addition.
>
Well: that's another problem. It would in fact complicate the language -
not syntactically but semantically, since you want to introduce another
*domain operator* to the language. A domain operator constructs types,
f.e. "struct", "union", "enum" are domain operators, because they
construct new domains (they are type building blocks). Adding a domain
operator to C++ language is very expensive, because the whole (already
very compilicated) type system has to be modified to support the new
operator: You have to handle conversion, overloading, ambiguity
resolution, storage requirements and all that stuff for a new family of
types (plus: it has to be implemented in you debugger!)
I dont't think that the propososal will find interceders, given that C++
offers a cheap and safe way to implement the feature.
--
Marco
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "Noah Stein" <noah@vision-scape.com>
Date: Tue, 24 Jul 2001 18:09:05 CST Raw View
> With respect, I suggest that the above code is too long and verbose and I
am
> suggesting replacing it with 2 lines of code:
>
> bitfield WindowStyle { Child, Border, Parent, FatBorder };
> WindowStyle ws = Child | Border;
>
> Now this is itself a compelling reason to adopt my suggestion, your code
may
> work, but it is hardly as readable as my 2 lines are. And to be honest the
> usage we have right now in Windows is hardly likely to be replaced by your
> code as it is much longer to type (Windows programmers are notoriously
lazy)
> and is less succinct.. The code I suggest is even more succinct and
compact
> than current code, far far less error prone and checked by the compiler.
>
> Let me just try to rejustify my (HONEST) request for a new feature!
> Seriously all Windows programmers use this bitfields stuff everyday and
> there is no support for it in the compiler. Every single Window has a set
of
> unique winow styles, radio buttons, edit boxes, trees, everything. And
since
> I started using Windows years ago I have had more than one occassion to
use
> this bitfield concept for a kind of style on my own classes (I suggest
that
> it is in fact a idiom - al la Copland). I am saying that a very poor,
error
> prone alternative is in use daily by programmers, and that this simple and
> clear addition would make one more aspect of large complex programs for
> Windows verifiable by compiler, and that further it wouldn't compilcate
the
> language syntax and is in fact a 'cheap' addition.
I also do extensive Win32 programming, but I don't think that the bitfields
situation warrants a change in the language. I spent about 20 minutes
fooling around with VC++ 6.0, and I came up with the following:
enum Type { Child = 1, Border = 2, Parent = 4 };
class Styles;
class Style
{
DWORD val;
public:
Style(const Type t) : val((DWORD)t) {}
operator DWORD() const
{ return val; };
};
class Styles
{
DWORD val;
public:
Styles(const DWORD v) : val(v) {}
operator DWORD() const
{ return val; }
};
Styles operator+(const Styles lhs, const Styles rhs)
{
return Styles((DWORD)lhs|(DWORD)rhs);
}
Styles operator-(const Styles lhs, const Styles rhs)
{
return Styles((DWORD)lhs&(~(DWORD)rhs));
}
class WindowStyle
{
DWORD style;
public:
WindowStyle() : style(0) {};
WindowStyle(const Styles s) : style((DWORD)s) {}
operator DWORD() const
{ return style; }
WindowStyle& operator+=(const Styles rhs)
{ style |=(DWORD)rhs; return *this; }
WindowStyle& operator-=(const Styles rhs)
{ style&=~(DWORD)rhs; return *this; }
WindowStyle& operator=(const Styles rhs)
{ style = (DWORD)rhs; return *this; }
};
I went with a slightly different notation than you did because I find it
prettier, but it could change it to exactly mimic your notation with little
effort. I can use the above as follows:
WindowStyle s2(Child);
WindowStyle s3(Child+Border+Parent);
s3 -= Border;
s2 += Parent;
With a little effort, the code above could be templated according to the
type used to hold the value (all the references to DWORD) and the allowable
elements of the set (all the references to Type). Creating new sets would
then involve defining and enum set and specifying the template. After the
initial template is written, it would be no more effort than your proposal.
It's a solution that is an order of magnitude better than a language change
for Win32 programming because any language change would take years to
trickle through the standards bodies and then at least a year for MS to
implement in VC++ (or much more if you look at their current feature
implementation backlog).
-- Noah
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "Joe Borkoles" <undertoad@btinternet.com>
Date: Sun, 22 Jul 2001 17:31:34 GMT Raw View
I know C++ needs new language features like a leper needs to roll around in
a fungus filled pit of liquid trash, but.......
1. open up / extend the memory allocation functions to allow, for instance,
people to write their own memory allocation checkers.
----------------------------------------------------------------------------
-------------------------------------------------------
For example I can overload new()/delete() and new[]/delete[] BUT I can't
find out what class invoked the call - now we have RTTI this seems like a
nice idea
Also access to static initialisation stuff, perhaps something like
set_new_handler(),
e.g.. set_static_init_handlers( void* pre_handler, void* post_handler) and
set_static_cleanup_handlers( ...
(ps anyone thinks that the pre-processor can handle this - well yes, some of
it, but no, I have an aversion to it, and there are some things that are
just to hideous to code, ie most things connected with the pre-processor).
cost: Almost nothing, I bet most compilers already have a hidden api to do
this for commercial memory checker handlers.
2. Proper support for the bitfields concept so widely used in modern
programming.
----------------------------------------------------------------------------
-------
Right now we have bitset<> and enums, but it just won't do!
for example
enum WindowStyles { Child, Parent, Border, FatBorder, etc, 32 }
typedef bitset<32> WindowStyle;
great! I can now say
WindowStyle style_;
style |= Child | FatBorder;
The trouble is this is at best an almost there situation
because the bitset typedef and the enum are only loosely coupled, given
another enum, like:
enum MyEnum { ChocoBar, MaltedDrink, 32 };
the compiler lets me say
styles_ |= ChocoBar;
And I seriously doubt any programmer would want this.
I need/want a strong association, a compiler enforced check that the type I
am putting my bitfield enum elements into are as declared.
I propose:
bitfield WindowStyle { Child, Parent, Border, FatBorder };
...
WindowStyle ws( Child | FatBorder );
..
ws &= ~FatBorder;
ws |= Border;
This saves on strange looking notation (ie the ,N at the end of enum) and
only allows previously defined values of WindowStyle to be put into
something of type WindowStyle, and the user is free from worrying about the
size of the type as well.
cost: 1 tiny, super cheap new keyword (stands back as numerous c++ committe
member keyboards/pc's go up in flames)
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: marco@technoboredom.net (Marco Manfredini)
Date: Mon, 23 Jul 2001 19:11:12 GMT Raw View
"Joe Borkoles" <undertoad@btinternet.com> wrote in
news:9jehpu$huv$1@uranium.btinternet.com:
> I know C++ needs new language features like a leper needs to roll
> around in a fungus filled pit of liquid trash, but.......
>
>
> 1. open up / extend the memory allocation functions to allow, for
> instance, people to write their own memory allocation checkers.
> --------------------------------------------------------------------
> -------- -------------------------------------------------------
>
> For example I can overload new()/delete() and new[]/delete[] BUT I
> can't find out what class invoked the call - now we have RTTI this
> seems like a nice idea
> Also access to static initialisation stuff, perhaps something like
> set_new_handler(),
>
> e.g.. set_static_init_handlers( void* pre_handler, void*
> post_handler) and
> set_static_cleanup_handlers( ...
>
> (ps anyone thinks that the pre-processor can handle this - well
> yes, some of it, but no, I have an aversion to it, and there are
> some things that are just to hideous to code, ie most things
> connected with the pre-processor).
>
> cost: Almost nothing, I bet most compilers already have a hidden
> api to do this for commercial memory checker handlers.
>
> 2. Proper support for the bitfields concept so widely used in
> modern programming.
> --------------------------------------------------------------------
> -------- -------
>
> Right now we have bitset<> and enums, but it just won't do!
>
> for example
>
> enum WindowStyles { Child, Parent, Border, FatBorder, etc, 32 }
> typedef bitset<32> WindowStyle;
>
> great! I can now say
>
> WindowStyle style_;
>
> style |= Child | FatBorder;
>
a) you suggest to define the set of WindowStyles as bitset<32>, so how
is the compiler supposed to know, that only WindowStyles can make it
into _styles?
b) "style |= Child | FatBorder;" is mathematically, logically or
whateverly nonsense. "Child" and "FarBorder" are *not* sets (they are
enumerated Elements), so there cannot be an union operation between
them. (this only works, when the enum members are defined to match bit
positions, which means that they are treated as single-element sets)
> The trouble is this is at best an almost there situation
> because the bitset typedef and the enum are only loosely coupled,
> given another enum, like:
>
> enum MyEnum { ChocoBar, MaltedDrink, 32 };
>
> the compiler lets me say
>
> styles_ |= ChocoBar;
>
> And I seriously doubt any programmer would want this.
>
Here is the Obvious Sample(tm) for what you want:
#include <iostream>
using namespace std;
enum Flags { Read, Write, Share };
template<class T>
struct SetOf
{
struct BoolRef
{
SetOf<T> &set;
T fl;
operator bool () { return set.hasMember(fl); };
BoolRef & operator=(bool b)
{
if (b) set<<fl; else set>>fl;
return *this;
}
BoolRef(SetOf<T>&_set, T _fl) : set(_set), fl(_fl) {}
};
unsigned values;
SetOf& operator << (T fl)
{
values |= (1<<fl);
return *this;
}
SetOf operator >> (T fl)
{
values &= ~(1<<fl);
return *this;
}
boolRef operator ->* (T fl)
{
return BoolRef(*this, fl);
}
bool hasMember(T fl)
{
return (0!=(values & (1<<fl)));
}
};
int main()
{
SetOf<Flags> f;
f<<Read <<Write >>Share ; // set read, write, but not share
cout << f->*Write << f->*Read << f->*Share << endl;
f>>Read; // unset read
f->*Share=true; // set Share
cout << f->*Write << f->*Read << f->*Share << endl;
}
Feel free to adapt this to your needs.
--
Marco
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: Steve Clamage <clamage@eng.sun.com>
Date: Mon, 23 Jul 2001 19:15:19 GMT Raw View
On Sun, 22 Jul 2001, Joe Borkoles wrote:
> 1. open up / extend the memory allocation functions to allow, for instance,
> people to write their own memory allocation checkers.
> -------------------------------------------------------
Well, you can already do that, via at least two different mechanisms.
> For example I can overload new()/delete() and new[]/delete[] BUT I can't
> find out what class invoked the call - now we have RTTI this seems like a
> nice idea.
Class don't invoke operator new (or delete). Only a new-expression
(delete-expression) invokes operator new (delete).
You can put an operator new and delete into a class. They will
be invoked for allocating or deallocating objects of that class
type or derived class types.
class C {
public:
void* operator new(size_t); // only for C or derived class
void operator delete(void*); // ditto
...
};
You can create a "placement" version of operator new that takes
addtional parameters, which could be (for example) RTTI data for
the type of the object being created.
void* operator new(size_t, const std::type_info&); // placement new
C* p = new (typeid(C)) C; // use placement new
> Also access to static initialisation stuff, perhaps something like
> set_new_handler(),
>
> e.g.. set_static_init_handlers( void* pre_handler, void* post_handler) and
> set_static_cleanup_handlers( ...
You'll have to explain what problem you are trying to solve for
which a good solution does not already exist.
---
Steve Clamage, stephen.clamage@sun.com
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]