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

时间:2018-01-24 23:20:48

标签: c++ function templates

我想写类型为整数时应该调用的模板函数,例如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
}

3 个答案:

答案 0 :(得分:5)

是的,这是可能的。一种方法是使用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造成其中一个重载&#34;无法编译&#34;如果不满足条件,这意味着由于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
    }
}

答案 1 :(得分:3)

根据您的完整意图,在SFINAEstd::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;
}

希望可以提供帮助。

答案 2 :(得分: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.