如何将任意大小的位集传递给函数?

4
以下程序可以成功编译。
#include <iostream>
#include <bitset>

void foo(std::bitset<10> n)
{
    std::cout << n.size() << "\n";
}

int main()
{
    std::bitset<10> n;
    foo(n);
}

$ g++ -std=c++11 -Wall -Wextra -pedantic foo.cpp
$ ./a.out 
10

我该如何修改foo()函数,使其能够接受任意尺寸的bitset
3个回答

10

这就是 模板 的作用。因此,将 foo 设为一个带有非类型模板参数的函数模板:

template<std::size_t N>
void foo(std::bitset<N> n)
{
    std::cout << n.size() << "\n";
}

那么

std::bitset<10> n10;
foo(n10);
std::bitset<20> n20;
foo(n20);

2

std::bitset<N>是一种类型,因此您可以创建一个接受通用类型的模板函数。

template <typename T>
void foo (T n)
 { std::cout << n.size() << "\n"; }

请注意,此函数不仅适用于所有std::bitset,还适用于所有具有size()成员的类型,该成员返回可以发送到std::cout的值,例如许多STL容器(std::setstd::vectorstd::map等)。
因此,例如,您也可以按以下方式调用foo()
 std::vector<int> v(20);
 foo(v);

根据您的要求,这可能是好事或坏事。

如果您想要一个仅接受std::bitset的函数,那么您可以按照songyuanyao建议的解决方案进行操作:您可以显式指定std::bitset并将维度模板化。

template <std::size_t N>
void foo (std::bitset<N> n)
{ std::cout << n.size() << "\n"; }

但在这种情况下,不需要使用 size();可以直接使用 N

template <std::size_t N>
void foo (std::bitset<N>)
{ std::cout << N << "\n"; }

如果您希望foo接受一个std::bitset<N>,并且N在一定范围内(例如[10,20[),您可以使用C++11的SFINAE,编写以下内容。
template <std::size_t N>
typename std::enable_if<(N >= 10U) && (N < 20U)>::type foo (std::bitset<N>)
 { std::cout << N << "\n"; }

现在您已经拥有:
std::bitset<10> n10;
std::bitset<15> n15;
std::bitset<25> n25;

foo(n10);    // compile
foo(n15);    // compile
// foo(n25); // compilation error

-1

你也可以使用 auto,比模板声明需要的代码少得多

#include <iostream>
#include <bitset>

void foo(auto n)
{
    std::cout << n.size() << "\n";
}

int main()
{
    std::bitset<15> n;
    foo(n);
}   

我认为模板版本相比您的版本会提供更易理解的错误信息。 - Incomputable
会的,但在当前任务(显示动态位集的大小)中,它能正常工作。 - Nikita Krupitskas
2
这还不是标准的C++。 - Brian Bi
1
很不幸,将auto作为函数参数放在lambda之外还不是标准的C++。 - TartanLlama
这很奇怪,因为我在cpp.sh/8xzss上尝试了一下,它可以正常运行。 - Nikita Krupitskas
2
这是一个编译器扩展。它很可能会作为概念的一部分被采纳,但目前还没有。 - TartanLlama

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接