Board index » cppbuilder » Re: ANSI/ISO marches on

Re: ANSI/ISO marches on


2005-11-02 10:55:34 AM
cppbuilder100
Boian Mitov < XXXX@XXXXX.COM >writes:
Quote
Hi Alisdair,

1. Post constructors and pre destructors capable of executing
virtual functions tops my list.
Interesting idea. :)
Quote
2. Initialization of member variables in the class body.
Re-inforces bad habits. No real gain, so why bother making such a
big change to the language?
Quote
3. A modifier that will force error of a member variable is not
initialized in the constructor.
Should this apply only to types that would be left with indeterminate
values? What if the member has a default constructor? This might be
a nice compiler option for emitting a warning, if nothing else.
Quote
4. Improved RTTI ( More information about at least functions with a
modifier or something. )
Something would be nice in this area, even if only, like you say, for
functions. That would greatly help writing unit tests and such, which
use function name convention to determine what is a test case.
Has anyone heard anything about Stroustrup's XTI library idea? Is he
still working on this? It would be an alternate that would certainly
make this, and much more, entirely possible and even easy.
Quote
5. A labeled loops, or similar mechanism, so we can break outer loops.
Nice, but already doable with a simple goto. They are in the language
for a reason... :)
Quote
I also was not able to find a property library. I remember that
there ware talks about work being done on implementing properties as a
standard library. So far no sign of it.
Do you mean like Borland's PMI proposal, or something else? (Theirs
was not accepted, IIRC.)
--
Chris (TeamB);
 
 

Re:Re: ANSI/ISO marches on

Chris Uzdavinis (TeamB) wrote:
Quote
>2. Initialization of member variables in the class body.
Re-inforces bad habits. No real gain, so why bother making such a
big change to the language?
Reduces bugs and improves readibility and maintainability. How many
times you had to go trough all the constructors one by one and change an
initialization velue to a new one, and how many times you have missed a
constructor? I have done it thousands of times.
Quote
>3. A modifier that will force error of a member variable is not
>initialized in the constructor.

Should this apply only to types that would be left with indeterminate
values? What if the member has a default constructor? This might be
a nice compiler option for emitting a warning, if nothing else.
It shoudl probably have a modifier so you can mark any variable as
such. Currently we use const and ref items to somewhat achieve the goal
at least for some cases, but it is not possible with normal variables :-( .
Quote
>5. A labeled loops, or similar mechanism, so we can break outer loops.

Nice, but already doable with a simple goto. They are in the language
for a reason... :)
Goto does usually confuse the compiler optimisations. The labeled
loops will play well with optimisers. They also are located at the front
of the loop, as opose to adding at the end which improves readability.
Quote

>I also was not able to find a property library. I remember that
>there ware talks about work being done on implementing properties as a
>standard library. So far no sign of it.


Do you mean like Borland's PMI proposal, or something else? (Theirs
was not accepted, IIRC.)

I mean something like :
class MyClass
{
public:
property<int>Width;
public:
MyClass() :
Width( &MyClass::GetWidth, &MyClass::SetWdth );
};
Cheers,
Boian
 

Re:Re: ANSI/ISO marches on

Boian Mitov wrote:
Quote
I mean something like :
Like this ? This is taken from code I wrote a while ago. Modified to be
portable:
#include <stdio.h>
class JFBase
{
public:
JFBase() { };
~JFBase() { };
};
template <class T>class JFProperty : public JFBase
{
public:
typedef void (JFBase::*SetterEvent)( T Value );
typedef T (JFBase::*GetterEvent)();
private:
JFBase *Owner;
SetterEvent SetEvent;
GetterEvent GetEvent;
public:
JFProperty()
{
Owner = NULL;
SetEvent = NULL;
GetEvent = NULL;
};
JFProperty( JFBase *POwner, SetterEvent PSetEvent = NULL, GetterEvent
PGetEvent = NULL )
{
Owner = POwner;
SetEvent = PSetEvent;
GetEvent = PGetEvent;
};
~JFProperty() { };
T operator =( const T &C )
{
if( SetEvent )
(Owner->*SetEvent)( C );
if( GetEvent )
return (Owner->*GetEvent)();
else
return C;
};
operator T()
{
if( GetEvent )
return (Owner->*GetEvent)();
else
return NULL;
};
};
class MyClass : public JFBase
{
private:
int FWidth;
void SetWidth( int PWidth )
{
FWidth = PWidth;
printf( "Width has been set to %d.\n", FWidth );
};
int GetWidth()
{
printf( "Width is being retrieved. Returning %d.\n", FWidth );
return FWidth;
}
public:
MyClass() : Width( this, (JFProperty<int>::SetterEvent)(
&MyClass::SetWidth ), (JFProperty<int>::GetterEvent)(
&MyClass::GetWidth ) )
{
FWidth = 0;
printf( "Width is inited to %d.\n", FWidth );
};
JFProperty<int>Width;
};
int main()
{
int w;
MyClass mc;
mc.Width = 45;
w = mc.Width;
printf( "w = %d.\n", w );
return 0;
}
Jonathan
 

{smallsort}

Re:Re: ANSI/ISO marches on

Boian Mitov < XXXX@XXXXX.COM >writes:
Quote
>>2. Initialization of member variables in the class body.
>
>Re-inforces bad habits. No real gain, so why bother making such a
>big change to the language?

Reduces bugs and improves readibility and maintainability. How
many times you had to go trough all the constructors one by one
and change an initialization velue to a new one, and how many
times you have missed a constructor? I have done it thousands of
times.
Have you thought of defining a constant and use that to initialize the
member? It allows you to simply modifiy the constant's value in this
case.
 

Re:Re: ANSI/ISO marches on

Boian Mitov wrote:
Quote
1. Post constructors and pre destructors capable of executing
virtual functions tops my list.
Experience with the VCL tells me this is a really bad idea! (all the
problems of OnCreate all over again)
I guess you are after a separate chain of constructors/destructors to
be called after/before the initial chain of constructors/destructors -
2 phase construction. There are idioms for doing this today, but I
guess enforcing them in the compiler could guarantee the second phase
is never accidentally forgotten.
If I throw an exception in the second construction phase, which
destructors should be called? All the pre-destructors? None of them?
Predestructors for base classes that successfully constructed the
second phase? [Remembering all virtual calls dispatch via top-level
class in predestructor]
Same question for exceptions thrown in construction phase 1. Should we
pre-destruct fully constructed bases / members?
I think it is clearly a bad idea for bases, but I am not so sure about
members. And this gives a new twist on the private base vs member
debate.
Quote
2. Initialization of member variables in the class body.
No. You really don't want this in the standard, no matter how much you
think you want to use it.
Initialization is already a much bigger mess than you would ever
believe without reading the fine print (I doubt anyone outside a
specialist on the committee understands all the interactions/nuances
today, including most the rest of the committee)
Any extension to initialization simply complicates matters, and
initializing outside the initializer list (and therefore out of
decalaration order?) breaks many of the assumptions the destructor
rules are based on - for clean up of partially constructed objects for
instance.
The IS a lot of work looking at how to simply initialization, such as
providing a consistent new syntax that can be used everywhere - so
initialization in an initializer list or a local variable declaration
look identical.
Quote
3. A modifier that will force error of a member variable is not
initialized in the constructor.
Watch this space <g>
Quote
4. Improved RTTI ( More information about at least functions with a
modifier or something. )
The need for a 'reflection' API is noted, and has been studied. There
are no clear answers on how to implement this efficiently though, so I
doubt it will make the next standard. I expect to continue looking
though.
There continues to be work on compile time reflection though, notably
through 'concepts'. This is something that sets C++ apart from other
languages today, although we jump through many template tricks to make
it happen. One aim is that we can forget the phrase 'template tricks'
after the next standard, as the need will go away, and the techniques
will become accessible/desirable to the working programmer, rather than
the specialist.
Quote
5. A labeled loops, or similar mechanism, so we can break outer loops.
We are looking into a new for-loop syntax, to automatically iterate
over ranges/containers, but labelled loops has not been highlighted as
a need. As Chris says, you can use goto today.
Quote
I am sure a lot could be done in the direction of contracts etc.
There is indeed a proposal actively being worked on in committee. I am
not sure if this will make the final cut or not - it depends on how
much work will be involved stabilising the specification, vs working on
other features. It is one of the more significant features still being
worked on though.
Quote
I also was not able to find a property library. I remember that there
ware talks about work being done on implementing properties as a
standard library. So far no sign of it.
The property library was put forward as a counter to implementing
properties in the language. Properties as a concept got a mixed
reaction. The way they masquerade as variables is dangerous in a
context sensitive language. Imagine how they might interact with
templates, for instance. The library solution would avoid a lot of
problems with core language changes, making their use more optional.
However, even the people putting the library forward were not inclined
towards it, so it has not been suggested for a library TR yet. I guess
I should consider pushing it forward again myself, although I am very
much in the 'midly against' camp. Experience with BCB tells me I need
reflection much more than I need property syntax.
--
AlisdairM(TeamB)
 

Re:Re: ANSI/ISO marches on

"Alisdair Meredith [TeamB]" < XXXX@XXXXX.COM >writes:
Quote
Boian Mitov wrote:


>1. Post constructors and pre destructors capable of executing
>virtual functions tops my list.

Experience with the VCL tells me this is a really bad idea! (all the
problems of OnCreate all over again)
Post-constructor and pre-destructor hooks wouldn't be like OnCreate
because they would run exclusively during the well-defined lifetime of
the object. Of course, such hooks would be useless unless they were
not executed until post-most-derived-type-constructor or before
most-derived-type-constructor.
Then you have to worry about ordering, probably in a bottom-up
fashion. (Most derived class's post-constructor hook runs first, then
its parent, and last, the root class of the hierarchy, and with MI,
would be in right-to-left order. Etc. For Destruction, it would go
in exactly the opposite order.
Neat, I think. That way you could get some auto-invoked virtual
functions without having 2-phase construction having to be manually
implemented and hidden away behind a proxy interface.
--
Chris (TeamB);
 

Re:Re: ANSI/ISO marches on

Hi Boian,
Quote
1. Post constructors and pre destructors capable of executing virtual
functions tops my list.
That's a good one. Currently I have to do another layer of wrapping to
achieve this result. Post-constructors can be implemented by making the
constructor private and introducing a public static function (usually
called Create) as a replacement for the destructor. It works best with
heap allocated objects, so T::Create can just return T*. These are the
workarounds that we have currently.
Quote
2. Initialization of member variables in the class body.
I like what Thomas Maeder suggested, even if it's not as convenient as
you would expect:
class Test
{
public:
Test();
private:
int value;
static const int value_default = 10;
};
Test::Test()
: value(value_default)
{ }
Quote
3. A modifier that will force error of a member variable is not
initialized in the constructor.
I have a workaround for this. I know it's not the same as a language
feature, it may introduce ambiguities and other problems, esp. with
templates, but in plain simple cases it would work I think:
template <typename T>
class forceinit_type
{
public:
explicit forceinit_type(const T& source) : value(source) { }
forceinit_type& operator=(const T& source) { value = source; return
*this; }
operator T() const { return value; }
forceinit_type& operator++() { ++value; return *this; }
forceinit_type operator++(int) { return value++; }
forceinit_type& operator--() { --value; return *this; }
forceinit_type operator--(int) { return value--; }
forceinit_type& operator+=(const T& op) { value += op; return *this; }
forceinit_type& operator-=(const T& op) { value -= op; return *this; }
forceinit_type& operator*=(const T& op) { value *= op; return *this; }
forceinit_type& operator/=(const T& op) { value /= op; return *this; }
forceinit_type& operator%=(const T& op) { value %= op; return *this; }
forceinit_type& operator|=(const T& op) { value |= op; return *this; }
forceinit_type& operator&=(const T& op) { value &= op; return *this; }
forceinit_type& operator^=(const T& op) { value ^= op; return *this; }
forceinit_type& operator<<=(int op) { value <<= op; return *this; }
forceinit_type& operator>>=(int op) { value <<= op; return *this; }
private:
T value;
};
#ifdef _DEBUG
# define forceinit(T) forceinit_type<T>
#else
# define forceinit(T) T
#endif
// Usage:
class Test
{
public:
Test() : i1(10), d1(3.14) { }
private:
forceinit(int) i1;
forceinit(double) d1;
};
Quote
4. Improved RTTI ( More information about at least functions with a
modifier or something. )
Have you ever seen this?
www.garret.ru/~knizhnik/cppreflection/
www.garret.ru/~knizhnik/cppreflection/docs/reflect.html
I started working on something similar, which would automatically deduce
the type information from an identifier, such as
TypeOf(identifier)::name - returns the name of a variable or function as
a string
TypeOf(identifier)::is_member - determines whether identifier is a
member of a class
TypeOf(identifier)::kind - can tell if identifier is a function or a
variable
Here's my test code. I know it's just a start, but a step forward to the
good direction, I think. I can already deduce the typename string from
relatively complicate derived types. Treat it as a proof of concept, not
as a library or a final solution. Theoretically it's very extensible,
and for user classes the only thing that needs to be implemented is the
TypeName<T>overload. I appreciate any feedback on this.
class C
// Test case
{
public:
int i;
void f() { }
int f2(int) { return 0; }
};
template <class T>
inline bool IsField(T) { return false; }
template <class C, class T>
inline bool IsField(T C::*f) { return true; }
template <class T>
inline bool IsMethod(T) { return false; }
template <class C, class RT>
inline bool IsMethod(RT (C::*f)()) { return true; }
template <class C, class RT, class A1>
inline bool IsMethod(RT (C::*f)(A1)) { return true; }
template <class C, class RT, class A1, class A2>
inline bool IsMethod(RT (C::*f)(A1, A2)) { return true; }
template <class C, class RT, class A1, class A2, class A3>
inline bool IsMethod(RT (C::*f)(A1, A2, A3)) { return true; }
struct TypeInfo
{
std::string name;
bool is_member;
enum KindEnum { Function, Variable };
KindEnum kind;
};
template <class T>
struct TypeName
{
};
template <>
struct TypeName<int>
{
static std::string value() { return "int"; }
};
template <>
struct TypeName<void>
{
static std::string value() { return "void"; }
};
/*inline TypeInfo TypeOf(int)
{
TypeInfo i;
i.name = "int";
i.is_member = false;
i.kind = TypeInfo::Variable;
return i;
}*/
template <typename T>
inline TypeInfo TypeOf(T t)
{
TypeInfo i;
i.name = TypeName<T>::value();
i.is_member = false;
i.kind = TypeInfo::Variable;
return i;
}
template <class C, class T>
inline TypeInfo TypeOf(T C::*f)
{
TypeInfo i;
i.name = TypeName<T>::value();
i.is_member = true;
i.kind = TypeInfo::Variable;
return i;
}
template <class C, class RT>
inline TypeInfo TypeOf(RT (C::*f)())
{
TypeInfo i;
i.name = TypeName<RT>::value() + " (*)(void)";
i.is_member = true;
i.kind = TypeInfo::Function;
return i;
}
template <class C, class RT, class A1>
inline TypeInfo TypeOf(RT (C::*f)(A1))
{
TypeInfo i;
i.name = TypeName<RT>::value() + " (*)(" + TypeName<A1>::value() + ")";
i.is_member = true;
i.kind = TypeInfo::Function;
return i;
}
void Test()
{
// Form1->Caption = IntToStr(IsMethod(&C::f2));
Form1->Caption = TypeOf(&C::f).name.c_str();
// Form1->Caption = TypeOf(&C::i).name.c_str();
// int v; Form1->Caption = TypeOf(v).name.c_str();
}
Tom
 

Re:Re: ANSI/ISO marches on

Tamas Demjen wrote:
Quote
template <typename T>
inline TypeInfo TypeOf(T t)
Oops, I like this better:
template <typename T>
inline TypeInfo TypeOf(const T& t)
[...]
Tom