x6herbius x6herbius - 10 months ago 47
C++ Question

Cannot convert NULL to a pointer-to-object type

I've not been able to find an explanation of the following on Google so far, and it's confusing me a little.

I have a

which stores hierarchies of
. The
acts as a templated
factory, so that bookkeeping can be done when a
subclass instance is created or deleted. Both of these classes are in a dynamically linked module of their own and are within a module namespace (not sure whether this matters).

The (simplified)
class looks like this:

// SceneObject is a base class, but is not pure.
class SceneObject
// The parent Scene needs to be able to access protected functions.
friend class Scene;

// This is protected to enforce the factory design pattern.
// We don't want SceneObjects created without being tied to a Scene.
SceneObject(Scene* parentScene, SceneObject* parentObject);


And the (simplified)
class looks like this:

class Scene

// General bookkeeping - a fully constructed subclass is required
// here as the subclass constructor sets certain member variables.
void processSceneObjectCreated(SceneObject* object);

// This function means we can do:
// SceneObjectSub* obj = scene.createSceneObject<SceneObjectSub>(...)
// and pass whatever parameters are required for that particular
// subclass' constructor, while ensuring the Scene can keep a record
// of the created object.
// We can't call processSceneObjectCreated() in the SceneObject base
// class' constructor, as the required subclass constructor will not
// have been run yet.
template<typename T, typename... Args>
T* createSceneObject(Args... args)
T* obj = new T(this, std::move(args)...);
return obj;


As a test, I compiled the following code to create a new

ModuleNS::Scene scene;
ModuleNS::SceneObject* sceneObject =

However, the MSVC compiler gave me the following error:

Cannot convert argument 2 from 'int' to 'ModuleNS::SceneObject*'

This confused me, as I thought
(ie. 0) could always be converted to a pointer type. If instead I use
, or
(which I'd like to use, but for the sake of consistency with old code I've been using
instead), the compile error goes away.

What specifically causes NULL to stop being castable to a pointer?

Answer Source

The error has the same nature as the one in the following sample

template <typename T> void foo(T t) {
    void *p = t; // ERROR here

int main() {

In C++ only literal 0 can be converted to pointer type to produce null-pointer value. NULL expands to a literal zero, which is why you can use it to initialize/assign/compare with pointers directly. "Directly" is the key word here.

But once you feed it through a function parameter, it is no longer a literal 0 and can no longer act as a null-pointer constant.

In the above example T is deduced as some integer type. Inside the function t is just a [run-time] integer that happens to have value 0. And you are not allowed to initialize pointers with arbitrary integers.

Note that in modern C++ NULL can actually be defined as nullptr, which will make the above code to compile. But with the "traditional" definition of NULL (as integral 0) it won't.