null assignment in a template
This is a multi-part message in MIME format.
------=_NextPart_000_0112_01C79DF5.9B9881C0
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
Please excuse me if there is a better place for this post. I could not =
find one in MS's communities. My question is about template programming =
in C++, not really about STL.
// Initialised supplies an initial value in the variable declaration =
itself
// NOTE: for non-scalar types (such as floating point types) this =
template won't compile
// due to the fact that it is illegal to declare a template with a =
non-scalar value
// Use Uninitialised instead, and declare the value in its explicit ctor
template <typename T, T * zero>
struct Initialised<T*, zero>
{
Initialised() : m_value(zero) { }
template <typename U> Initialised(const U* that) : m_value(that) { }
template <typename U> T* & operator = (const U* that) { if =
(m_value != that) m_value = that; return *this; }
T* & operator = (const int constant) { return m_value = =
constant; }
operator T* & () { return m_value; }
operator const T* & () const { return m_value; }
T * m_value; // the plain old data
};
What I really want is to allow myself to declare a plain old pointer and =
guarantee that its initialized in the constructor or point of =
declaration, to make it much easier to avoid uninitialized variables =
issues.
The above appears to do exactly that.
The only fly in the ointment is that the following fails:
Initialised<Widget*, new Widget(1,2,3)> m_pWidget;
....blah - blah
....some code...
....later
m_pWidget = NULL;
Since this line evaluates to Initialised::operator = (int) { m_value =
= int; }
There is no conversion from int to Widget*!
Now, I can certainly do the obnoxious thing and cast int to Widget* in =
operator=(int), and then leave it up to the user to ensure that any =
int assignments are always the value NULL, but that's just sloppy and =
asking for trouble.
I can go back to my code that uses m_pWidget and force all =
null-assignments to be type-cast at the point of assignment:
m_pWidget = (Widget*)NULL;
Not the worst idea in the universe, but I have a lot of places where I'd =
like to replace the current variable / member declarations with =
Initialised<Type,zero> declarations, and I don't want to have to comb =
through many hundreds of lines of code to correct every NULL assignment.
What I Really Want(tm) is to be able to have m_pWidget = NULL evaluate =
to a valid expression, and m_pWidget = =
<any-other-integer-or-other-non-convertible-type> to error with "no =
conversion from <type> to Widget*".
I keep thinking that if I can make the operator = (x) partially =
specialized for operator = (NULL) I would be golden! However, =
everything I've tried leads to a compiler error. I need a type for NULL =
which is different from not-null and for the compiler to identify that =
such that the function called in m_pWidget = NULL is one function =
(that is legal), and m_pWidget = 5 results in an illegal assignment.
Any ideas / feedback would be *hugely* appreciated.
Steve Wolf
PS: Its Initialised instead of Initialized due to the fact that I =
already have an Initialized template for POD structs, and I wanted one =
for simple singular data types as well.
------=_NextPart_000_0112_01C79DF5.9B9881C0
Content-Type: text/html;
charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META http-equiv=Content-Type content="text/html; =
charset=iso-8859-1">
<META content="MSHTML 6.00.6000.16448" name=GENERATOR>
<STYLE></STYLE>
</HEAD>
<BODY bgColor=#ffffff background="">
<DIV><FONT face=Arial size=2>Please excuse me if there is a better =
place for
this post. I could not find one in MS's communities. My =
question is about template programming in C++, not really about
STL.</FONT></DIV>
<DIV><FONT face=Arial size=2></FONT> </DIV>
<DIV><FONT face=Arial size=2><FONT color=#008000>// Initialised =
supplies an
initial value in the variable declaration itself<BR>// NOTE: for =
non-scalar
types (such as floating point types) this template won't compile<BR>// =
due to
the fact that it is illegal to declare a template with a non-scalar =
value<BR>//
Use Uninitialised instead, and declare the value in its explicit
ctor<BR></FONT><FONT color=#0000ff>template <typename T, T *
zero><BR>struct Initialised<T*, =
zero><BR>{<BR>
Initialised() : m_value(zero) { }<BR> template =
<typename
U> Initialised(const U* that) : m_value(that) { =
}<BR>
template <typename U> T* & operator = (const U* that) { if =
(m_value !=
that) m_value = that; return *this; }<BR></DIV></FONT></FONT>
<DIV><FONT face=Arial size=2><FONT =
color=#0000ff> T* &
operator = (const int constant) { return m_value = constant;
}<BR></FONT></DIV></FONT>
<DIV><FONT face=Arial color=#0000ff size=2> =
operator T* &
() { return m_value; }<BR> operator const T* & () =
const {
return m_value; }<BR> T * m_value; <FONT =
color=#008000>// the
plain old data</FONT><BR>};</FONT></DIV>
<DIV><FONT face=Arial size=2></FONT> </DIV>
<DIV><FONT face=Arial size=2>What I really want is to allow myself =
to declare a
plain old pointer and guarantee that its initialized in the constructor =
or point
of declaration, to make it much easier to avoid uninitialized variables
issues.</FONT></DIV>
<DIV><FONT face=Arial size=2></FONT> </DIV>
<DIV><FONT face=Arial size=2>The above appears to do exactly =
that.</FONT></DIV>
<DIV><FONT face=Arial size=2></FONT> </DIV>
<DIV><FONT face=Arial size=2>The only fly in the ointment is that =
the following
fails:</FONT></DIV>
<DIV><FONT face=Arial size=2></FONT> </DIV>
<DIV><FONT face=Arial size=2>Initialised<Widget*, new =
Widget(1,2,3)>
m_pWidget;</FONT></DIV>
<DIV><FONT face=Arial size=2>...blah - blah</FONT></DIV>
<DIV><FONT face=Arial size=2>...some code...</FONT></DIV>
<DIV><FONT face=Arial size=2>...later</FONT></DIV>
<DIV><FONT face=Arial color=#800000 size=2>m_pWidget = =
NULL;</FONT></DIV>
<DIV><FONT face=Arial size=2></FONT> </DIV>
<DIV><FONT face=Arial size=2>Since this line evaluates to =
Initialised::operator
= (int) { m_value = int; }</FONT></DIV>
<DIV><FONT face=Arial size=2></FONT> </DIV>
<DIV><FONT face=Arial size=2>There is no conversion from int to
Widget*!</FONT></DIV>
<DIV><FONT face=Arial size=2></FONT> </DIV>
<DIV><FONT face=Arial size=2>Now, I can certainly do the obnoxious =
thing and
cast int to Widget* in operator=(int), and then leave it up to the =
user to
ensure that any int assignments are always the value NULL, but that's =
just
sloppy and asking for trouble.</FONT></DIV>
<DIV><FONT face=Arial size=2></FONT> </DIV>
<DIV><FONT face=Arial size=2>I can go back to my code that uses =
m_pWidget and
force all null-assignments to be type-cast at the point of
assignment:</FONT></DIV>
<DIV><FONT face=Arial size=2></FONT> </DIV>
<DIV><FONT face=Arial size=2>m_pWidget = =
(Widget*)NULL;</FONT></DIV>
<DIV><FONT face=Arial size=2></FONT> </DIV>
<DIV><FONT face=Arial size=2>Not the worst idea in the universe, but =
I have a
lot of places where I'd like to replace the current variable / member
declarations with Initialised<Type,zero> declarations, and I don't =
want to
have to comb through many hundreds of lines of code to correct every =
NULL
assignment.</FONT></DIV>
<DIV><FONT face=Arial size=2></FONT> </DIV>
<DIV><FONT face=Arial size=2>What I Really Want(tm) is to be able to =
have
m_pWidget = NULL evaluate to a valid expression, and m_pWidget =
<any-other-integer-or-other-non-convertible-type> to error with =
"no
conversion from <type> to Widget*".</FONT></DIV>
<DIV><FONT face=Arial size=2></FONT> </DIV>
<DIV><FONT face=Arial size=2>I keep thinking that if I can make the =
operator =
(x) partially specialized for operator = (NULL) I would be =
golden!
However, everything I've tried leads to a compiler error. I need a =
type
for NULL which is different from not-null and for the compiler to =
identify that
such that the function called in m_pWidget = NULL is one function =
(that is
legal), and m_pWidget = 5 results in an illegal =
assignment.</FONT></DIV>
<DIV><FONT face=Arial size=2></FONT> </DIV>
<DIV><FONT face=Arial size=2>Any ideas / feedback would be *hugely*
appreciated.</FONT></DIV>
<DIV><FONT face=Arial size=2></FONT> </DIV>
<DIV><FONT face=Arial size=2>Steve Wolf</FONT></DIV>
<DIV><FONT face=Arial size=2></FONT> </DIV>
<DIV><FONT face=Arial size=2>PS: Its Initialised instead of =
Initialized due to
the fact that I already have an Initialized template for POD structs, =
and I
wanted one for simple singular data types as =
well.</FONT></DIV></BODY></HTML>
------=_NextPart_000_0112_01C79DF5.9B9881C0--