2015-05-14 2 views
7

Я читал «Эффективный современный C++» С. Мейерса, и я нашел что-то, что я не могу оборачивать вокруг.Почему проверка типов внутри шаблонов более строгая?

Пункт 8 объясняет, почему nullptr должен быть более чем 0 или NULL. Основной аргумент в пользу nullptr - более безопасное поведение при разрешении перегрузки. На практике вы избегаете непреднамеренного смешения между указателями и целыми типами, но это не вопрос моего вопроса.

Чтобы добраться до моего фактического вопроса, рассмотрим следующий код, который основан на примере, использованном в книге:

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

Первые три прямые вызовы f1, f2 и f3 компилировать штраф за либо 0 , NULL, или nullptr как пустой указатель. Последующие 3 вызова, которые выполняются с помощью функции шаблонов CallFun, гораздо более придирчивы: вы должны использовать nullptr, или конверсия между целыми типами (0 и NULL) будет принята. Другими словами, проверка типов кажется более строгой, когда она встречается внутри шаблона. Может кто-нибудь уточнить, что происходит?

+0

Я задал один и тот же вопрос :) См. Ссылку на dupe, которую я положил, и также см. Стандартные кавычки. – vsoftco

ответ

7

CallFun выводит тип PtrType для 0 и NULL как int, которые не неявно преобразовать в тип указателя.

Если вы хотите увидеть, что я имею в виду, просто попробуйте хранить 0 и NULL в auto «d переменного первый и вызов f1 в f2 от этих переменных. Они не будут компилироваться.

0 и NULL сами неявно отбрасываются на тип указателя, потому что они являются буквальными значениями, которые я предполагаю. Вероятно, в стандарте есть что-то, но, думаю, вы понимаете.

+0

Стоит отметить, что 'decltype (NULL)' не может быть 'int' для каждого компилятора. Единственное требование состоит в том, что литерал может быть неявным образом применен к любому типу указателя, поэтому «NULL» может быть определен как «nullptr». – Pubby

+0

@pubb цитата? – Yakk

+2

[support.types]/3: «Макрос NULL - это константа нулевого указателя C++, определяемая реализацией». [conv.ptr]/1: «Константа нулевого указателя - это целочисленный литерал со значением 0 или значением типа« std :: nullptr_t' ». – TartanLlama

Смежные вопросы