我正在尝试用这样的签名编写一个函数:
template<typename From, typename To>
To bar(From in){...}
此函数需要具有不同的行为,具体取决于To
是浮点类型还是整数类型。 (假设From
是完整的并且都是算术的)
这可以使用if constexpr(std::is_integral<To>::value) {...} else {...}
轻松实现,但我仅限于没有if constexpr
的C ++ 11。
实施这种专业化的好方法是什么?
答案 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我建议更改模板参数From
和To
的声明顺序,然后您可以在调用时明确指定第一个模板参数。例如bar<int>(...);
和bar<float>(...);
。
如果要为除积分和浮点类型以外的类型获得更清晰的消息,可以添加另一个重载。 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_type
,T
为整数类型,或来自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_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