Re: null assignment in a template



Steve Wolf wrote:
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; }

That conditional check is redundant.
int i = 5;
i = i; //perfectly ok.

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;

That isn't going to compile, since the second arg must be an extern pointer value, or NULL. Did you mean:
Initialised<Widget*, NULL> m_pWidget(new Widget(1,2,3));
?

...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*!

Right.

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.

Why not just assign to 'zero' inside the member, since this assignment operator is for re-zeroing only, presumably?

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.

How about dropping the const int operator, and adding this:

private:
struct Dummy {};
public:
T* & operator= (int Dummy::*) { return m_value = zero; }
template <typename U>

It's impossible to pass anything to that function other than NULL, since user code cannot form any other pointer-to-member of Dummy, since Dummy is private.

Tom
.



Relevant Pages

  • RE: Error 2027 while compiling template function within class template
    ... Seems to compile fine with VC++6. ... declare a class which derives from a template that is based upon the class ... you are trying to declare. ...
    (microsoft.public.vc.language)
  • Re: null assignment in a template
    ... My question is about template programming ... and declare the value in its explicit ... An assignment operator taking an int and one ... taking a pointer? ...
    (microsoft.public.vc.stl)
  • Re: null assignment in a template
    ... // this template won't compile due to the fact that it is illegal to ... and declare the value in its explicit ... delcares a single ctor to force the client to have to declare an initial value for said variable, as oppossed to Inialisedwhich allows for a compile-time constant initialization value to be specified in the template parameters themselves. ... taking a pointer? ...
    (microsoft.public.vc.stl)
  • Re: Template problem
    ... template ... struct Inner; ... A workaround is to only forward declare the Inner class when you declare ...
    (microsoft.public.vc.language)
  • Re: Problem overriding >> and << in a template class
    ... the rejection also mentioned the cause the of problem: ... For the friend functions to work correctly you need to declare them ... to use a template argument list in the friend declaration. ...
    (comp.lang.cpp)