根据模板参数不等式执行不同的函数

Execute different functions depending on template parameter disequation

本文关键字:函数 执行 不等式 参数      更新时间:2023-10-16

这绝对是一个微不足道的问题,但我不知道如何做到这一点。

我有一个模板函数,比如template <unsigned int N> void my_function()。现在,我对my_function有两种不同的实现,如果N大于100,则应该使用第一种实现,如果N小于100,则应该使用另一种实现。

我尝试像这样使用SFINAE:

template <unsigned int N, typename = enable_if <N >= 100> :: type> my_function()
{
   // First implementation
}
template <unsigned int N, typename = enable_if <N < 100> :: type> my_function()
{
   // Second implementation
}

但是这是两次声明同一个函数。然后我试着做一些像

template <unsigned int N, bool = (N >= 100)> my_function();

然后用布尔值的两个不同值实现这两个函数。没有成功,因为它是部分专门化。

然后我尝试将N包装为struct参数和函数调用中的bool,但它在特化类之前特化了一个成员函数,这是不能做的。

是否有合理的方法来做到这一点?

试试这个:

#include <type_traits>
#include <iostream>
template <unsigned int N, typename std::enable_if <N >= 100> :: type* = nullptr> 
void my_function()
{
    std::cout << "N >= 100" << std::endl;
}
template <unsigned int N, typename std::enable_if <N < 100> :: type* = nullptr> 
void my_function()
{
   std::cout << "N < 100" << std::endl;
}
int main()
{
    my_function<42>();
    my_function<100>();
}

模板默认参数不参与重载(因此SFINAE不适用)。另一方面,在上面的代码片段中,依赖模板的非类型参数位于赋值的左侧,因此SFINAE开始起作用。

如果您出于某种原因不喜欢enable_if,您可以选择标签调度:

#include <type_traits>
class low {};
class high {};
template <int N, class T>
   void func(T, low)
   {
      // version for high N
   }
template <int N, class T>
   void func(T, high)
   {
      // version for low N
   }
template <int N, class T>
   void func(T val)
   {
      func<N>(val, std::conditional_t<(N>=100), high, low>{});
   }
int main()
{
   func<3>(3.14159); // low version
   func<256>("Yo"); // high version
}

在这种情况下,我们可以将标记限制为简单的东西,如true_type和谬误,但通常这可能是另一种方法。

您可以对返回类型使用SFINAE:

template <unsigned int N>
enable_if_t<(N >= 100)> my_function()
{
   // First implementation
}
template <unsigned int N>
enable_if_t<(N < 100)> my_function()
{
   // Second implementation
}

目前,您只有template <unsigned int N, typename T>T的默认类型不同。

对于部分专门化,您可以转发到结构:

template <unsigned int N, bool = (N >= 100)>
struct my_function_impl;
template <unsigned int N>
struct my_function_impl<N, true>
{
    void operator () const { /* First implementation */}
};
template <unsigned int N>
struct my_function_impl<N, false>
{
    void operator () const { /* Second implementation */}
};
template <unsigned int N>
void my_function() { my_function_impl<N>{}(); }