C ++模板 - 浮点和积分类型的不同专业化

时间:2018-05-06 03:36:20

标签: c++ c++11 templates template-specialization

我正在尝试用这样的签名编写一个函数:

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

此函数需要具有不同的行为,具体取决于To是浮点类型还是整数类型。 (假设From是完整的并且都是算术的)

这可以使用if constexpr(std::is_integral<To>::value) {...} else {...}轻松实现,但我仅限于没有if constexpr的C ++ 11。

实施这种专业化的好方法是什么?

2 个答案:

答案 0 :(得分:4)

您可以将模板重载与SFINAE一起使用。 e.g。

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) {
    ...
}

BTW我建议更改模板参数FromTo的声明顺序,然后您可以在调用时明确指定第一个模板参数。例如bar<int>(...);bar<float>(...);

LIVE

如果要为除积分和浮点类型以外的类型获得更清晰的消息,可以添加另一个重载。 e.g。

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.");
}

答案 1 :(得分:0)

如果您确定To类型是整数或浮点数,另一种可能的解决方案是使用标记调度

使用std::is_integral<T>继承std::true_typeT为整数类型,或来自std::false_type的事实,否则,您可以写bar()(使用由songyuanyao建议的From / To订单更改,如下所示

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

并开发两个具有不同签名的foo()模板函数(std::true_typestd::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