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

4

1 回答 1

3

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

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

第二个调用可能会让您感到惊讶,但实际上 cv 限定符是从非类右值中删除的,因此强制转换表达式恰好int仍然具有 type 。所以函数模板的参数类型会被推断为int&——编译失败。

现在,C++0x 之前的版本bind只支持非 const 引用作为它转发的参数类型,所以如果你给它一个 const 参数就可以了——它的模板化参数会让它变成一个 const 引用。但是如果你给它一个非常量参数,并且它是一个右值,那就不行了因为它不能被引用参数绑定。

您想使用左值调用绑定对象 - 即使用sc或使用它强制转换为 const 左值。另请注意,函数参数类型的顶级限定符被删除,因此foo有效地具有类型void(int, int)- 这种顶级 cv 删除发生在所有类型的参数中。无论如何,解决方案是将调用更改为

for(int sc = 0; sc < 10; sc+=interval){
   func((int const&)sc); // notice &
}
于 2009-11-05T10:26:49.627 回答