Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is type checking inside templates more strict? [duplicate]

I was reading Effective Modern C++ by S. Meyers, and I found something I can't quite wrap my head around.

Item 8 explains why nullptr should be preferred over 0 or NULL. The main argument in favor of nullptr is a safer behavior in overload resolutions. In practice you avoid unintended mixups between pointers and integer types, but this is not the point of my question.

To get to my actual question, consider the code below, which is based on the example used in the book:

#include <memory>

class MyClass {
    int a;
};

// dummy functions that take pointer types
int    f1(std::shared_ptr<MyClass> spw){return 1;};  
double f2(std::unique_ptr<MyClass> upw){return 1.0;};
bool   f3(MyClass* pw){return true;};

// template that calls a function with a pointer argument
template<typename FuncType,
         typename PtrType>
auto CallFun(FuncType func, PtrType ptr) -> decltype(func(ptr))
{
    return func(ptr);
}

int main()
{
    // passing null ptr in three different ways
    // they all work fine int this case
    auto result1 = f1(0);        // pass 0 as null ptr to f1
    auto result2 = f2(NULL);     // pass NULL as null ptr to f2
    auto result3 = f3(nullptr);  // pass nullptr as null ptr to f3 }

    // passing null ptr in three different ways through the template
    // only nullptr works in this case
    auto result4 = CallFun(f1, 0);         // compile error!
    auto result5 = CallFun(f2, NULL);      // compile error!
    auto result6 = CallFun(f3, nullptr);   // OK

    return 0;
}

The first three direct calls to f1, f2 and f3 compile fine for either 0, NULL, or nullptr as a null pointer. The subsequent 3 calls, which are performed through the templates function CallFun are much more picky: you have to use nullptr, or no conversion between integer types (0 and NULL) will be accepted. In other words type checking seems to be more strict when it occurs inside the template. Can somebody clarify what is going on?

like image 273
Emerald Weapon Avatar asked May 14 '15 12:05

Emerald Weapon


1 Answers

CallFun deduces the type of PtrType for 0 and NULL as int, which don't implicitly convert to a pointer type.

If you want to see what I mean, just try storing 0 and NULL in an auto'd variable first, and calling f1 an f2 from those variables. They won't compile.

0 and NULL themselves implicitly cast to a pointer type because they're literal values I guess. There's probably something about it in the standard but I think you get the point.

like image 83
KABoissonneault Avatar answered Sep 22 '22 02:09

KABoissonneault