Функция, возвращающая удвоение, когда ожидается долгое

Недавно я ответил на другой вопрос, и в моем ответе был следующий код.

template<typename T, typename ... Ts>
struct are_arithmetic{
    enum {
        value = std::is_arithmetic<T>::value && are_arithmetic<Ts...>::value
    };
};

template<typename T>
struct are_arithmetic<T>{
    enum {
        value = std::is_arithmetic<T>::value
    };
};

template<typename Arg, typename = std::enable_if_t<std::is_arithmetic<Arg>::value>>
Arg max(Arg arg){
    return arg;
}

template<typename Arg, typename Arg1, typename ... Args, typename = typename std::enable_if_t<are_arithmetic<Arg, Arg1, Args...>::value>>
auto max(Arg arg, Arg1 arg1, Args ... args){
    auto max_rest = max(arg1, args...);
    return arg > max_rest ? arg : max_rest;
}

Теперь из этого кода я предположил, что max() вернет максимальное число из заданного списка чисел, а также сохранит его тип.

Но когда оригинальный постер попробовал код:

int main(){
    auto res = max(1.0, 2, 3.0f, 5, 7l);
    std::cout << typeid(res).name() << " "  << typeid(7l).name();
}

Он получил d l из стандартного выхода

Это показывает, что возвращаемый тип функции совсем не тот, который ожидается. Почему функция не возвращает long?

2 ответа

Решение

Мне кажется, что когда max() функция называется как:

auto res = max(1.0, 2, 3.0f, 5, 7l);

Затем с учетом своей подписи:

auto max(Arg arg, Arg1 arg1, Args ... args){
    auto max_rest = max(arg1, args...);
    return arg > max_rest ? arg : max_rest;
}

Вот, Arg очевидно, будет double,

Тогда возвращаемое значение является троичным оператором:

return 1.0 > max_rest ? 1.0 : max_rest;

Не важно что max_rest Завершается. Допустим, это действительно long, Итак, у вас есть троичный оператор, с одним double выражение, и один long выражение.

Мне кажется, что long Выражение будет повышен до типа doubleтак что возвращение auto тип является double,

Тип возврата

template<typename Arg, typename Arg1, typename ... Args, typename = typename std::enable_if_t<are_arithmetic<Arg, Arg1, Args...>::value>>
auto max(Arg arg, Arg1 arg1, Args ... args){
    auto max_rest = max(arg1, args...);
    return arg > max_rest ? arg : max_rest;
}

не зависит от значения, но от данного типа. Так что здесь он возвращает общий тип всех аргументов.

Другие вопросы по тегам