2015-11-19 2 views
3

Рассмотрим следующий код:Делегат параметр nullptr для перегрузки указателя в коде шаблона

#include <iostream> 

template<typename T> // generic 
void f(T) 
{ 
    std::cout << __PRETTY_FUNCTION__ << std::endl; 
} 

template<typename T> // overload for pointer types 
void f(T*) 
{ 
    std::cout << __PRETTY_FUNCTION__ << std::endl; 
} 

int main() 
{ 
    int* p{nullptr}; 
    f(p);  // correct delegation to f<T*>(); 
    f(nullptr); // calls f<T>(); 
} 

Live on Coliru

Как вы можете видеть, вызывая f(nullptr) результаты в общей f(T) называют, а не от перегрузки указателя f(T*). Это довольно раздражает. Я знаю, почему это происходит: потому что nullptr имеет тип std::nullptr_t, а общий шаблон имеет более высокий ранг перегрузки.

Как я могу «решить» эту проблему в простой форме? Я могу, конечно, написать две разные реализации: одну для указателей и одну для nullptr_t, а затем иметь общий, который отправляет один из двух через некоторый SFINAE, но это выглядит слишком сложно.

+0

Как вы можете ожидать, что перегрузка 'T *' будет вызываться, когда 'std :: nullptr_t' не имеет типа, на который указывает? Я думаю, что вам действительно нужна отдельная логика для этого случая, так что вы можете добавить третью перегрузку. – Brian

+1

@Brian Я не ожидаю, что 'f (T *)' будет вызван, я бы хотел получить это поведение без особых проблем. – vsoftco

+3

Что вы ожидаете от 'T', когда вы вызываете' f (T *) '? – clcto

ответ

6

Самый простой способ, вероятно, будет осуществлять перегрузку void f(std::nullptr_t) и отправку к одной из реализаций указателей, которые могут быть выбраны вами, предполагая, что он делает правильную вещь (независимо правильно есть) для нулевых указателей:

void f(std::nullptr_t) { f(static_cast<void *>(nullptr)); } 
Смежные вопросы