#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”来确保如果函数的参数通过引用传递,则计数器变量不会被意外更改。
答案 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 &
}