是否可以根据类型是整数类型还是浮点类型重载模板函数

Is it possible to overload a template function based on whether the type is an integer type or a floating point type?

本文关键字:类型 重载 函数 整数 是否      更新时间:2023-10-16

我想编写模板函数,该函数应该在类型为整数时调用,例如int8,int16,int32,int64,uint8,uint16,uint32,uint64;以及另一个具有不同代码的模板函数(同名(,仅用于FLOAT类型float32,float64...无论如何可以使用C++中的模板函数来做到这一点?例如:

template <class T>
void fun(T b)
{
   /// Code for integer type
}

 template <class S>
void fun(S a)
{
   /// Code for floating type
}

是的,这是可能的。一种方法是使用SFINAE:

template <class T, std::enable_if_t<std::is_integral_v<T>, int> = 0>
void fun(T b)
{
   /// Code for integer type
}

template <class S, std::enable_if_t<std::is_floating_point_v<T>, int> = 0>
void fun(S a)
{
   /// Code for floating type
}

请注意,enable_if的 2 个条件必须是不相交的,我们可以从std::is_integralstd::is_floating_point的文档中看到它们是不相交的。如果不是这样,条件必须看起来像std::is_integral_v<T> && !std::is_floating_point_v<T>

这里发生的事情是,如果不满足条件,std::enable_if_t会使其中一个重载"无法编译",这意味着由于 SFINAE,根本不考虑重载。


如果您使用的是 C++17,您可能需要考虑改用if constexpr

template <class T>
void fun(T b)
{
    if constexpr (std::is_integral_v<T>) {
        /// Code for integer type
    } else if constexpr (std::is_floating_point_v<T>) {
        /// Code for floating type
    }
}

根据您的全部意图,在 SFINAE 和 std::enable_if 之外,您还可以使用常规函数重载和/或模板专用化:

#include <iostream>
#include <cstdint>
template < typename T >
void fun(T b)
{
    std::cout << "Generic called: " << b << std::endl;
}
void fun(int16_t b)
{
    std::cout << "int16_t: " << b << std::endl;
}
void fun(int32_t b)
{
    std::cout << "int32_t: " << b << std::endl;
}
void fun(float b)
{
    std::cout << "float: " << b << std::endl;
}
template <>
void fun<int64_t>(int64_t b)
{
    std::cout << "int64_t specialization: " << b << std::endl;
}
int main(int argc, char** argv)
{
    double dbl = 3.14159;
    float flt = 1.12345;
    int16_t i16 = 16;
    int32_t i32 = 32;
    fun(dbl);
    fun(flt);
    fun(i16);
    fun(i32);
    fun(5.555f);
    fun(32);
    fun(std::numeric_limits<int64_t>::max());
    return 0;
}

希望能有所帮助。

根据SFINAE,我们可以为一种类型设计编译错误,同时让另一种类型进入模板替换阶段。在整型与浮点型的情况下,我们可以对整数使用与位相关的运算符,例如 ~ 。例如

#include <iostream>
template <typename T, T=~0>
void f_(T a, int)  // additional tags for unambiguous overloading, same below
{
    std::cout << a << " is of integral type." << std::endl;
}
template <typename T>
void f_(T a, char)
{
    std::cout << a << " is of floating-point type." << std::endl;
}
template <typename T>
void f(T a)
{
    f_<T>(a, 0);
}

int main()
{
    f<char>('a');
    f<int>(0);
    f<float>(1.5f);
    f<double>(2.5);
    return 0;
}

a is of integral type.
0 is of integral type.
1.5 is of floating-point type.
2.5 is of floating-point type.