C++函数可以在一个参数中交替接收两种类型吗?

w3nuxt5m  于 2023-02-06  发布在  其他
关注(0)|答案(4)|浏览(131)

我想给一个函数发送一个整数,这个整数可能是8/16位,这取决于条件。我可以声明一个函数来接收int 8/in 16作为参数吗,这取决于调用者发送的是什么?或者,我必须声明两个函数,每种类型一个(我现在正在做的)吗?
无效函数(uint8_t/uint16_t值)

无效函数(uint8_t值)无效函数(uint16_t值)

uqxowvwt

uqxowvwt1#

这可以通过使用函数模板和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
}
axkjgtzd

axkjgtzd2#

@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

o3imoua4

o3imoua43#

在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
}
qvtsj1bj

qvtsj1bj4#

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() << '\n';

    // templated visitor
    std::visit(
        [](auto && val)
        {
            std::cout << "called with type " << typeid(val).name()
             << ", value " << val << '\n';
        },
        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)
        << '\n';
    }
    else if (std::holds_alternative<uint16_t>(value))
    {
        std::cout << "got uint16_t alternative " << std::get<uint16_t>(value)
        << '\n';
    }
}

相关问题