为什么for_each不能在这里选择正确的印刷品

时间:2014-09-11 15:40:33

标签: c++ templates

我编写了一个打印模板函数,它为bool类型值打印"True""False"

我尝试将其应用于for_each算法,但它不起作用。

输出仍为01。似乎模板专业化在for_each中不起作用。怎么会发生这种情况?

如何使代码按预期工作?

#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <ctime>

using namespace std;

template <typename T>
void _print(const T& i)
{
    cout<<i<<endl;
}
template <>
void _print<bool>(const bool& i)
{
    if (i == 0)
        cout<<"False"<<endl;
    else
        cout<<"True"<<endl;
}

class print
{
public:
  template <typename T>
  void operator()(const T& val) const { _print(val); };
};

int main()
{
  auto even = [&](int i)->bool{return (i%2==0);};
  srand(time(NULL));
  vector <int> test(3);
  generate(test.begin(),test.end(),[]()->int{return rand()%100;});
  for_each(test.begin(),test.end(),print());
  vector <bool> flag(3);
  transform(test.begin(),test.end(),flag.begin(),even);
  for_each(flag.begin(),flag.end(),print());

  return 0;

}

输出结果为:

34
23
3
1
0
0

但我希望:

34
23
3
True
False
False

2 个答案:

答案 0 :(得分:10)

std::vector<bool>的邪恶部分 vector<bool>::reference不是您所期望的bool,而是代理。

您可以添加额外的超载(如果您愿意,可以添加专业化):

void _print(const vector<bool>::reference& i)
{
    _print<bool>(i);
}

Live example

答案 1 :(得分:4)

问题是vector<bool>不是bool的容器。相反,它将多个“布尔”值打包到其存储的每个字节中,因此无法获得对任何bool值的引用。相反,取消引用迭代器会提供类型为vector<bool>::reference的“代理”对象,其行为类似于bool在某些情况下的引用,但并非所有情况。

在这种情况下,这还不够好;您对_print的专业化需要真正的const bool&引用,但_print会传递reference类型的对象,从中推断出通用模板。

您可以通过为此类型添加重载来支持vector<bool>作为特殊情况:

void _print(std::vector<bool>::reference r) {_print(bool(r));}

(顺便说一句,您不应该使用_print之类的reserved names