【问题标题】:Can a C++ function receive two types in one argument alternatively?C++ 函数能否在一个参数中交替接收两种类型?
【发布时间】:2023-02-07 00:50:06
【问题描述】:

我希望将一个整数发送给一个函数,该整数可能是 8/16 位,具体取决于条件。我可以声明一个函数来接收 int8/in16 作为参数,这取决于调用者发送的内容吗?或者,我是否必须为每种类型声明两个函数(我目前正在做的)?

void func(uint8_t/uint16_t 值)

或者

void func(uint8_t 值) void func(uint16_t 值)

【问题讨论】:

  • 您正在寻找template function
  • 你忘了template <typename T> void func(T value)
  • 如果函数是类中的方法,您也可以使用overloading。
  • @havakok 为什么将 python 答案链接到 C++ 问题?就学习 C++ 而言,那个 GFG 网站名声很低。
  • @PaulMcKenzie 我没有。它是我在投票关闭时误点击时自动生成的。删除了它。

标签: c++ function integer arguments


【解决方案1】:

这可以通过使用函数模板和 SFINAE 来完成,如下所示:

#include <cstdint>
#include <iostream>

template <typename T> std::enable_if_t<std::is_same_v<T, uint8_t>> func(const T& t)
{
    std::cout << "uint8 version called" <<std::endl;
}
template <typename T> std::enable_if_t<std::is_same_v<T, uint16_t>> func(const T& t)
{
    std::cout << "uint16 version called" <<std::endl;
}
int main()
{
     uint8_t x = 4;
     func(x);         //calls uint8 version

     uint16_t y = 4;
     func(y);         //calls uint16_t version
}

【讨论】:

  • 正如我的回答中提到的,这并没有回答这个问题,它要求一功能,而不是两个。
  • @cptFracassa 这怎么可能用一个函数来完成。 C++ 是一种静态类型语言。
  • Jason Liam:通过拥有一个模板功能,请参阅我的回答。
  • @cptFracassa 我同意,但请注意它非常琐碎的通过使用 || 将两个函数模板合并为一个(就像您在示例中所做的那样)。因此,如果 OP 真的只需要声明一次,那么他们就可以做到(因为这很简单,对 OP 来说是一个很好的练习)。这也很好,因为这样一来,我的回答就不会因为把那件琐碎的事情排除在外而完全用勺子喂食。
  • 杰森:我同意你最后的评论 +1。
【解决方案2】:

@Jason Liam 在上面,但如果你想要不同的功能,标准重载就是答案。如果您想对这两种类型使用单个函数,请结合 Jason 的函数:

#include <cstdint>
#include <iostream>
#include <typeinfo>

template <typename T> void func(const T& t) requires 
    std::is_same_v<T, uint8_t> || std::is_same_v<T, uint16_t>
{
    std::cout << "called with type " << typeid(T).name() <<std::endl;
}

int main()
{
     uint8_t x = 4;
     func(x);         //calls uint8_t version

     uint16_t y = 4;
     func(y);         //calls uint16_t version

     int z = 6;
//     func(z);  compiler error, z is not right type
}

Test in compiler explorer

【讨论】:

    【解决方案3】:

    使用 C++20,我们可以使用 requires 子句代替 SFINAE 来做同样的事情:

    #include <cstdint>
    #include <iostream>
    
    template <typename T> void func(const T& t) requires std::is_same_v<T, uint8_t>
    {
        std::cout << "uint8 version called" <<std::endl;
    }
    template <typename T> void func(const T& t) requires std::is_same_v<T, uint16_t>
    {
        std::cout << "uint16 version called" <<std::endl;
    }
    int main()
    {
         uint8_t x = 4;
         func(x);         //calls uint8 version
    
         uint16_t y = 4;
         func(y);         //calls uint16_t version
    }
    

    【讨论】:

      【解决方案4】:
      void func(uint8_t/uint16_t value)
      

      完全做到这一点的唯一方法(没有实例化为两个函数的函数模板)是使用 std::variant(或其他一些可区分的联合)。

      void func(std::variant<uint8_t, uint16_t> value)
      {
      }
      

      正是您所要求的。

      你几时开始实施在正文中,您会发现委托给模板化访问者通常更简单,然后您返回到现有答案(但是关于类型而不是静态类型的运行时决策相对昂贵)。

      示范in compiler explorer

      void func(std::variant<uint8_t, uint16_t> value)
      {
          std::cout << "called with type index " << value.index() << '
      ';
      
          // templated visitor
          std::visit(
              [](auto && val)
              {
                  std::cout << "called with type " << typeid(val).name()
                   << ", value " << val << '
      ';
              },
              value
              );
              
          // alternatively, test each type by hand
          if (std::holds_alternative<uint8_t>(value))
          {
              std::cout << "got uint8_t alternative " << std::get<uint8_t>(value)
              << '
      ';
          }
          else if (std::holds_alternative<uint16_t>(value))
          {
              std::cout << "got uint16_t alternative " << std::get<uint16_t>(value)
              << '
      ';
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-12-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-09-23
        相关资源
        最近更新 更多