代码之家  ›  专栏  ›  技术社区  ›  wcy

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

  •  0
  • wcy  · 技术社区  · 15 年前
    #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 回复  |  直到 15 年前
        1
  •  3
  •   Johannes Schaub - litb    15 年前

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

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

    第二个调用可能会让您感到惊讶,但实际上cv限定符是从非类rvalues中删除的,因此cast表达式恰好具有 int 仍然如此。因此,函数模板的参数类型将推导为 int& -编译失败。

    现在,前C++0X bind 只支持非常量引用作为它转发的参数类型,因此如果您给它一个常量参数,它是可以的-它的模板化参数将使它成为常量引用。但是如果你给它一个非常量参数,它是一个右值,它是 很好,因为它不能被引用参数绑定。

    您希望使用左值调用绑定对象,也就是说, sc 或者将其转换为常量值。还要注意,函数参数类型的顶级限定符被删除,因此 foo 有效地具有类型 void(int, int) -所有类型的参数都会发生顶级CV下降。无论如何,解决方案是将呼叫更改为

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