C++ 模板 - 浮点型和整型的不同特化

C++ Templates - Different Specialization for Floating and Integral types

我正在尝试编写一个带有如下签名的函数:

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

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

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

的 C++11

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

您可以在 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) {
    ...
}

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

LIVE

如果您想获得除整型和浮点类型之外的更清晰的消息,您可以添加另一个重载。例如

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

如果您确定 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_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