Параметр шаблона по умолчанию в Visual Studios 2012

Этот вопрос является продолжением после этого. Фактическая проблема заключается в том, что параметры шаблона по умолчанию для шаблонов функций не поддерживаются Visual Studios 2012, как указано в этот список.


Поскольку параметры шаблона по умолчанию не поддерживаются Visual Studios 2012, есть ли обходной путь, чтобы получить тот же результат без него? Итак, можно ли определить функцию шаблона, такую ​​​​как

template <typename T, typename Ret = T>
Ret round(T val, Ret ret = Ret()) {
    return static_cast<Ret>(
        (val >= 0) ?
        floor(val + (T)(.5)) :
        ceil( val - (T)(.5))
    );
}

без использования аргументов шаблона по умолчанию? Функция работает как

auto a = round(5.5, int()); // int a = 6
auto b = round(5.5); // double b = 6.0

person Didii    schedule 16.02.2014    source источник
comment
Вы всегда можете добавить перегрузку, например template<typename T> T round(T val);   -  person dyp    schedule 16.02.2014
comment
@dyp: исправлено. Спасибо. Перегрузка действительно работает. Меня смутил мой предыдущий пример из связанного вопроса. Это был не умный вопрос...   -  person Didii    schedule 16.02.2014
comment
Разве вы не хотите, чтобы округление по умолчанию соответствовало любому типу, который вы назначаете, а не типу ввода?   -  person Yakk - Adam Nevraumont    schedule 16.02.2014


Ответы (1)


Подобно этому, передача значения для принудительного возврата типа не очень хороший способ сделать это, вместо этого используйте аргумент шаблона:

#include <iostream>
#include <cmath>

template <typename Ret, typename T>
Ret round( T val ) {
    return static_cast<Ret>(
        ( val >= 0 ) ?
        std::floor( val + (T) ( .5 ) ) :
        std::ceil( val - (T) ( .5 ) )
        );
}

template <typename T>
T round( T val ) {
    return round<T,T>( val );
}

auto a = round<int>( 5.5 ); // int a = 6
auto b = round( 5.5 ); // double b = 6.0

static_assert( std::is_same<decltype(a), int>::value, "a must be int" );
static_assert( std::is_same<decltype(b), double>::value, "b must be double" );

int main() {
    std::cout << a << " " << b; 
}
person galop1n    schedule 16.02.2014
comment
Спасибо! Это ответ на оба моих вопроса. Я вставил round<T>(val) в качестве возвращаемого значения для перегруженной функции, что привело к ошибке компилятора. Я связал этот ответ с предыдущим вопросом. - person Didii; 16.02.2014
comment
Любопытно, round<int>(5) звонит куда? - person Yakk - Adam Nevraumont; 16.02.2014
comment
Неоднозначный вызов… Поскольку это обходной путь для отсутствующей функции, а вызов раунда с целочисленным вводом, вероятно, будет ошибкой, я бы использовал вместо этого template <typename T> auto round( T val ) -> typename std::enable_if< std::is_floating_point<T>::value, T>::type; и static_assert в версии с двумя аргументами, чтобы заставить T быть значением с плавающей запятой. - person galop1n; 16.02.2014