如果参数类型为“const int”,为什么无法编译tr1 :: bind

时间:2009-11-05 10:19:26

标签: const bind

#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <functional>
#include <deque>
using namespace std;

#include <tr1/functional>
using namespace std::tr1::placeholders;
template<class Function_t>
void for_each_x(Function_t func,int interval)
{
   for(int sc = 0; sc < 10; sc+=interval){
      func((const int)sc);
   }
}
void foo(int x,const int y)
{
}

int main(int argc, char *argv[])
{
   for_each_x(tr1::bind(tr1::function<void(int,const int)>(foo),_1,11),2);
   return 0;
}

gcc 4.2.2或4.4.1给出了很长的错误消息。 如果我将“const int”更改为“int”,则没有错误消息。 但我真的希望有“const int”来确保如果函数的参数通过引用传递,则计数器变量不会被意外更改。

1 个答案:

答案 0 :(得分:3)

表达式不仅按其类型进行分类,还按其左值进行分类。这个主要决定它是否存储在某个地方,它还决定了它是否可以绑定到非const引用。非const rvalue(非左值)不能绑定到非const引用,因此如果执行以下操作,则总是失败:

template<typename T>
void f(T&);
int main() { f(10); f((int const)10); }

第二个调用可能会让你感到惊讶,但实际上cv-qualifiers会从非类rvalues中删除,因此强制转换表达式恰好具有类型int。因此函数模板的参数类型将推导为int& - 编译失败。

现在,pre-C ++ 0x bind只支持非const引用作为它转发的参数类型,所以如果给它一个const参数就可以了 - 它的模板化参数会使它如此成为const引用。但是如果你给它一个非const参数,并且它是一个rvalue,那么就好了,因为它不能被引用参数绑定。

您希望使用左值调用绑定对象 - 即使用sc或将其强制转换为常量值。另请注意,函数参数类型的顶级限定符被删除,因此foo实际上具有类型void(int, int) - 这种顶级cv-dropping适用于所有类型的参数。无论如何,解决方案是将呼叫更改为

for(int sc = 0; sc < 10; sc+=interval){
   func((int const&)sc); // notice &
}