Is This Template Wrong?

closed account (zb0S216C)
I'm a little confused about my template function, or maybe templates in general. I have this function:

1
2
3
4
5
template < typename T >
bool CheckForNullptr( T *&Pointer )
{
    return( ( Pointer == nullptr ) ? true : false );
}

When I pass this function a pointer (short *Block), which of these two templates is equivalent:

A)

 
CheckForNullptr< short* >( short* *&Pointer );


B)
 
CheckForNullptr< short >( short *&Pointer );

Any help is appreciated.

Wazzak
Last edited on
If you pass a short* where a T* is needed, T becomes short.
I don't get your code. Why all the &s and the extra * in A? What are A and B supposed to be at all? Specializations?
Also, why not just pass a void*? That should work without any complaints.
Last edited on
Nothing wrong with it.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>

#define nullptr 0

template <typename T>
bool CheckForNullptr(T *&p)
{
        return p == nullptr;
}

int main()
{
        short* ps = 0;
        std::cout << CheckForNullptr(ps) << std::endl;

        return 0;
}

closed account (zb0S216C)
In A and B, I've replaced T with short/short* to simulate a call to CheckForNullptr( ). I just wanted
to know which of the code segments (A/B) is the equivalent.

hamsterman wrote:
Also, why not just pass a void* (sic)

Because void doesn't allow references to pointers. When it comes to pointers, especially the ones that point to resources, I prefer to work with the original, rather than create a copy.

kbw wrote:
#define nullptr 0 (sic)

I'm working with C++0x's nullptr, which isn't the standard zero :)

Edited in response to kbw's post.

Wazzak
Last edited on
return( ( Pointer == nullptr ) ? true : false );

Isn't this exactly the same as
return (Pointer == nullptr);
?

As hamsterman said, it's B.

There doesn't seem much point passing a reference to the pointer: CheckForNullptr(T*&). A pointer is not a large type so why not just pass the pointer by copy: CheckForNullptr(T*).

I have a few other pieces of advice, if you are interested.
1) Make the paramter constant: the function doesn't change it
2) If your compiler supports it (GCC/MinGW does, MSVC doesn't), you may as well make your function constexpr, so it can be evaluated at compile time given a constant argument.

Xander

EDIT:
I prefer to work with the original, rather than create a copy.

Forgive me for asking, but why!? :S
Last edited on
closed account (zb0S216C)
1) The compiler won't allow it.
2) VC++ doesn't support it.

Xander314 wrote:
Forgive me for asking, but why!? (sic)

Since I cannot make the parameter constant, and I pass a copy of a pointer that's pointing to an allocated block of resources, I may unintentionally delete the memory allocated by the original pointer; leaving the original pointer in a damaged state. If the user is unaware of the de-allocated resource, they may delete invalid pointer.

Wazzak
Last edited on
1
2
3
4
template <typename T>
bool CheckForNullptr(const T* const &Pointer) {
    return Pointer == nullptr;
}


The reference is overkill but it saves a copy of 32/64 bits. You can make the parameter constant like I just did. Also CheckForNullptr is not writing a new value so your explanation to Xander314 is wrong.
Last edited on
closed account (zb0S216C)
Mackabee, run this code and you'll see what I mean:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
template < typename T >
bool CheckForNullptr( const T * const Pointer )
{
    delete Pointer;
    return( ( Pointer == nullptr ) ? true : false );
}

int main( ) 
{
    short *Memory( new short( 10 ) );
    CheckForNullptr( Memory );

    delete Memory;
    Memory = nullptr;

    return 0;
}


Wazzak
Last edited on
Since I cannot make the parameter constant
why not?

Also, writing code with a goal to protect yourself from stupid things you might do must generate a whole lot of if( ptr != 0 )s. And be generally painful... If you don't trust yourself, either make everything const correct or use smart pointers everywhere. Or just move to a functional language.

edit: I tend to keep my posts not posted for a while..
If you expect yourself to throw a random delete somewhere, that's just paranoia. Also, in this case, having a reference wouldn't help you at all, since you don't set the pointer to 0.
Last edited on
Uh that's a completely different function lol

It would be pretty bad practice to name a function "Check" when "Check" clearly means to look and not to change
Last edited on
closed account (zb0S216C)
mackabee wrote:
Uh that's a completely different function lol (sic)

No, that's not the original; I was just expressing the following statement. I was stating that even though it's constant, It still isn't protected from deletion.

Framework wrote:
I may unintentionally delete the memory allocated by the original pointer; (sic)

I'll emphasize the word may.

Wazzak
But you write the function header in full knowledge of what the function will do. You should know that the CheckNullptr function isn't going to randomly delete something ^^
closed account (zb0S216C)
Xander314 wrote:
But you write the function header in full knowledge of what the function will do. You should know that the CheckNullptr function isn't going to randomly delete something ^^ (sic)

Misunderstanding much. I was basically saying that, even though the given pointer is constant, it doesn't protect the resources pointed to by the pointer from being deleted. Also, If you actually bothered to compile the code I previously posted, you'll actually receive an assertion error, due to the fact that the second call to delete attempts to delete memory that is no longer there (was deleted during the call to CheckForNullptr( )). Of course, I'm not thick, I do know the consequences of performing such actions; I was merely pointing out an issue.

Wazzak
Using a & won't save you from that.
Topic archived. No new replies allowed.