2009-09-23 50 views
3

我有一个简单的类是这样的:使用std :: bind2nd与引用

class A 
{ 
public: 
    void f(const int& n) 
    { 
     std::cout<<"A::f()" << n <<"\n"; 
    } 
}; 

,我试图用这样的:

std::vector<A> vec; 
A a; 
vec.push_back(a); 
std::for_each(vec.begin(), vec.end(), std::bind2nd(std::mem_fun_ref(&A::f), 9)); 

但是,当我编译代码我得到以下错误内部的功能的头文件某处:

错误C2529:“_right”:参照 参考是非法

如果我删除参数f()中的引用,它编译得很好。我该如何解决这个问题?我不想删除引用,因为在我的真实代码中复制对象的代价非常高。另外,我没有使用提升。

+0

您是否检查了此链接? http://www.velocityreviews.com/forums/t290345-stdmemfunref-and-bind2nd-question。html – vpram86 2009-09-23 08:11:19

回答

5

你不能这么做,很抱歉。只要考虑它不包括在std::bind1ststd::bind2nd(有点像3个参数的函数等)的情况之一。 Boost会有所帮助 - boost::bind支持透明地参考,也有boost::ref

如果您的实现支持TR1 - 最新的g ++版本和VC++ 2008 SP1都可以 - 那么您可以使用std::tr1::bind,它大部分与boost::bind相同,但是标准化。

+0

“标准化”有点夸张,我想。技术报告至多是一个准标准。不幸的是,它并没有说明如何包含头文件。 G ++采用风格,而在VC++中 - 纠正我,如果我错了 - 标题包含没有领先的“tr1 /”。 – sellibitze 2009-09-23 22:04:55

+0

那么,它仍然是一个由委员会设计的文件,可以被实现者重用。关于标题名称--TR规范始终将它们称为“”,因此没有歧义;如果g ++ _requires_' ',那么它不符合 - 但你确定这是一个要求,而不是一个选项?在任何情况下,'std :: tr1 :: bind'都被指定为不在新的单独头文件中,而是作为现有头文件''的补充。 – 2009-09-23 23:25:11

+0

我不同意你的解释,GNU显然也没有。见1.3/3-4。让我引用第4段:“建议标准头文件中的附加声明使用未默认定义的宏进行保护,否则,所有扩展头文件(包括具有非标准声明的标准头文件的新头文件和并行版本)放置在不属于默认搜索路径_的部分的_separate目录中 – sellibitze 2009-10-03 08:23:06

2

我不相信你可以将参数绑定到需要引用的方法。 (不在STL中,我认为升级版可能会让你这样做,但我不确定)

你需要自己推出。

struct CallF 
{ 
    CallF(int const& data): m_data(data) {} 
    void operator()(A& val) const 
    { 
     val.f(m_data); 
    } 
    int const& m_data; 
}; 

使用这样的:

std::for_each(vec.begin(), vec.end(), CallF(9)); 
0

实际上,编译器错误消息道出了原委:

错误C2529: '_right':引用来引用是非法

std :: binder将参数作为引用 - 你不能传递一个引用ar eference。

没办法。

1

我被同样的问题困住了。如果你看看C++标准,你会发现它实际上是一个“库缺陷”。符合C++的实现根本无法处理参考参数。 mem_fun_ref返回具有嵌套typedef的类的对象(

argument_type, first_argument_type, second_argument_type 

)其中引用未被除去。 bind1st和bind2nd被指定为有一个运算符(),它将引用作为参数。如果argument_type已经是引用,那么将无法编译。

一个解决方案可能是将memfunref替换为您自己的模板魔法,并删除嵌套的argument_type typedefs的引用。