Re: null assignment in a template



comp.lang.c++.moderated is the place for C++ question in general. The
unmoderated counterpart exists, but has a much worse signal to noise ratio.

Yes, I agree. I was unaware that I could access usenet via Google - but now that I can, I will move over there. Thanks.

// 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

I'm not sure what you mean with floating point types. Indeed, template
arguments are restricted to object types, function types, integral values
and (I think) pointers. All those need to be compile-time constants.

Sorry - that's referring to another template, Uninisialized<T>, which delcares a single (const T &) ctor to force the client to have to declare an initial value for said variable, as oppossed to Inialised<T> which allows for a compile-time constant initialization value to be specified in the template parameters themselves.

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
};

This looks mightily weird. An assignment operator taking an int and one
taking a pointer? Also, what is the value of 'zero' for? Isn't it a plain
null pointer? If you want a smart pointer that must be initialised, you
could use one that doesn't have a constructor without arguments.

I only declare member operator = (const int constant) to allow for Initialised<T*, NULL> p; p = NULL; Since NULL == 0, and not (void*)0, what other options do I have (this is the crux of my post)?

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.

Wait: either you need a plain old pointer or you get something with a
constructor. You can't modify the behaviour of a raw pointer to be
initialised!

The only fly in the ointment is that the following fails:

Initialised<Widget*, new Widget(1,2,3)> m_pWidget;

The new expression is not a compile-time constant, I wonder how this is
supposed to work.

D'oh! Right - only NULL or address of a global can be used for the second template argument.

So the only real issue is trying to get an Initialised<T*> p to later be assigned a NULL constant. This is what I'm trying to get to, since it is trivial to provide for T* assignment.

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;

Nah, that's way too twisted, and using C casts is a bad idea anyway.
static_cast<Widget*>(0) would be the way to go.

My point is that I don't want to have to cast it at all - I want my Initialised<T*> wrapper to act just like a T* and allow p = NULL, exactly as C++ would if it were unwrappered.

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.

How about using smart pointers? In particular this code could benefit from
the use of std::auto_ptr.

Smart pointers are great - and I use them extensively. Sometimes, fixing code to use a smart pointer is just more work than its worth, and ownership mechansims can be complex in legacy code, so all I really need to achieve is a guarantee that the pointer is initialized. At least, this can be a solid step forward in making legacy code more correct, without having to do an extensive analysis on it. Eventually, all of the legacy code can be updated to modern coding principles, but the reality of the situation dictates an incrmental approach. Hence my Initialised<> templates.

.



Relevant Pages

  • Re: Item 42 of Effective C++
    ... > variable in the class are of the template type? ... several times does not lead to code bloat, and that is probably also not ... void pointer. ... believe at least knowing a bit of assembler helps a lot for understanding ...
    (alt.comp.lang.learn.c-cpp)
  • Re: The Decline of C/C++, the rise of X
    ... > tend to be most useful for encoding Boolean values in data structures ... to freea pointer obtained from the gc, ... >> to be a useful attribute of a language. ... Template arguments are evaluated in the scope of the point of instantiation, ...
    (comp.programming)
  • 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)
  • Table of pointers to templated functions
    ... How do I declare a typedef of a pointer to a templated ... template ... void print_name ...
    (comp.lang.cpp)
  • Re: Template problem
    ... template ... struct Inner; ... A workaround is to only forward declare the Inner class when you declare ...
    (microsoft.public.vc.language)