2017-01-31 14 views
1

У меня есть эта функция шаблона для макснесовпадение данных и компилятор не может вывести аргумент шаблона

template <typename T> 
T max(T a, T b) { return (a > b) ? a : b; } 

И я хотел бы заменить эти:

int max(int a, int b){ return (a > b) ? a : b; } 
char cmax(char a, char b){ return (a > b) ? a : b; } 
unsigned int umax(unsigned int a, unsigned int b){ return (a > b) ? a : b; } 

мне нужно a и b иметь один и тот же тип.
Но мой код (который я портирования от C до C++) имеет такие вещи, как это: выход

size_t myvar; 
... 
... 
int i = max(myvar,5); 

VS2015:

Error C2672 'max': no matching overloaded function found  
Error C2672 'max': no matching overloaded function found 
Error C2782 'T max(T,T)': template parameter 'T' is ambiguous 
Error C2784 'T max(T,T)': could not deduce template argument for 'T' from 'int' 

Ладно, я, вероятно, следует бросить 5 к size_t.

Мой вопрос: почему C позволяет это? И что еще более важно, что происходит под капотом? Составляет ли компилятор 5 значение size_t или что? Каковы могут быть последствия этого?

Спасибо :)

+0

Обратите внимание, что ваша версия C имеет другие случаи сбоя, которые могут не генерировать предупреждение о компиляции, например. когда ввод больше, чем 'INT_MAX' –

ответ

2

В коде C, где вы звоните max, оба аргумента неявно преобразуются в тип int, так как параметры функции имеют тип int. Таким образом, myvar преобразуется в int (это не 5, который преобразуется в size_t). Следует избегать конверсии от size_t до int, поскольку она часто сужается (size_t часто длиннее int).

В C++ 14, вы можете написать max шаблон, который может принимать два аргумента разных типов следующим образом:

template <class T, class U> 
auto max(T a, U b) { 
    return (a > b) ? a : b; 
} 

В C++ 11, решение чуть более многословен:

template <class T, class U> 
typename std::common_type<T, U>::type max(T a, U b) { 
    return (a > b) ? a : b; 
} 

Тип возврата будет любым типом, который имеет тернарное выражение. Для двух целых типов разного размера будет выбран более длинный тип, поэтому никакая информация не будет потеряна. (Некоторая информация может быть потеряна, если один тип подписан, а другой - без знака, и оба имеют одинаковую длину.)

+0

Я думал о том, чтобы сделать ваше первое решение. Оба решения работают, хотя компилятор предупреждает о несоответствии unsigned/signed (size_t/int). Спасибо за объяснение! –