Шаблоны C ++ - различная специализация для плавающих и интегральных типов - PullRequest
0 голосов
/ 06 мая 2018

Я пытаюсь написать функцию с подписью, например, так:

template<typename From, typename To>
To bar(From in){...}

Эта функция должна иметь различное поведение в зависимости от того, является ли To плавающим или целочисленным типом. (при условии, что From является целым, и оба являются арифметическими)

Этого легко добиться, используя if constexpr(std::is_integral<To>::value) {...} else {...}, однако я ограничен C ++ 11, в котором нет if constexpr.

Какой хороший способ реализовать такую ​​специализацию?

Ответы [ 2 ]

0 голосов
/ 06 мая 2018

Если вы уверены, что тип To является целочисленным или плавающим, другое возможное решение - использование диспетчеризации тегов

Используя тот факт, что std::is_integral<T> наследуется от std::true_type, когда T является целочисленным типом, или от std::false_type, в противном случае вы можете написать bar() (используя также From / To изменение порядка, предложенное songyuanyao) следующим образом

template <typename To, typename From>
To bar (From inVal)
 { return foo<To>(inVal, std::is_integral<To>{}); }

и разработать две foo() шаблонные функции с разными сигнатурами (std::true_type или std::false_type для второго параметра) следующим образом

template <typename To, typename From>
To foo (From inVal, std::true_type const &)
 { std::cout << "foo() integral case: " << inVal << std::endl; return {0}; }

template <typename To, typename From>
To foo (From inVal, std::false_type const &)
 { std::cout << "foo() float case: " << inVal << std::endl; return {1}; }

Теперь звоню

bar<int>("abc");
bar<double>("xyz");

вы получите

foo() integral case: abc
foo() float case: xyz
0 голосов
/ 06 мая 2018

Вы можете использовать шаблонные перегрузки с SFINAE . например,

template<typename To, typename From>
typename std::enable_if<std::is_integral<To>::value, To>::type bar(From in) {
    ...
}

template<typename To, typename From>
typename std::enable_if<std::is_floating_point<To>::value, To>::type bar(From in) {
    ...
}

Кстати, я предлагаю изменить порядок объявления параметров шаблона From и To, тогда вы можете просто явно указать первый аргумент шаблона при их вызове. Такие как bar<int>(...); и bar<float>(...);.

ЖИТЬ

Если вы хотите получить более четкое сообщение для типов, отличных от целочисленных и с плавающей точкой, вы можете добавить еще одну перегрузку. например, * 1 016 *

template<class T> struct dependent_false : std::false_type {};

template<typename To, typename From>
typename std::enable_if<!std::is_integral<To>::value && !std::is_floating_point<To>::value, To>::type bar(From in) {
    static_assert(dependent_false<To>::value, "Types must be integral or floating point types.");
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...