占位符能否与ref()一起使用?

4

我正在使用c++11特性,并尝试了以下代码:

void dump(ostream &os, const MyType &mt)
{

}

void f(const vector<MyType> &mts, ostream &os)
{
   for_each(mts.begin(), mts.end(), bind(dump, ref(os), ref(_1));
}

这段代码在clang编译时出现错误:
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/stl_algo.h:4417:2: error: no matching function for call to object of type
      'std::_Bind<void (*(std::reference_wrapper<std::basic_ostream<char> >, std::reference_wrapper<const std::_Placeholder<1> >))(std::basic_ostream<char>
      &, const MyType &)>'
        __f(*__first);

如果我从_1中删除ref,它就可以正常编译:

for_each(mts.begin(), mts.end(), bind(dump, ref(os), _1);

似乎占位符不适用于引用,但希望确认一下,您能列出它为什么不适用的语义定义吗?它实际上已经通过引用传递了吗?


你的原始代码毫无意义。 - Bryan Chen
根据我的经验,要么某些东西非常简单,以至于bind不相关(这里就是这种情况),要么它非常复杂,使bind起作用将需要太多的工作。使用基于范围的循环,只需调用函数即可。 - Cheers and hth. - Alf
2
@Cheersandhth.-Alf:别忘了Lambda表达式:for_each(mts.begin(), mts.end(), [&os](const MyType &x) { dump(os, x); }); - rodrigo
1个回答

7

std::ref() 用于传递本来会被复制的引用值。

在您的代码中,它被用于传递 os,这是一个显然不希望复制的本地名称。

请记住,是调用 std::bind() 进行了复制。也就是说,std::bind() 返回的值持有每个传递对象的副本。而 std::ref() 防止了这种复制并保留了一个引用。

但是,占位符实际上不是 std::bind() 返回的对象中的值。相反,它们是一种标记,指示函数将第 n 个参数转发到封装函数。关键词在于“转发”:由于该值被转发,如果您的函数需要引用,则它将被作为引用传递,如果您的函数需要复制,则它将被作为副本传递。

由于 _1 不是要传递给函数的真实值,而是库的技巧,用 std::ref() 没有意义。


@LightnessRacesinOrbit:嗯,我认为OP担心的是dump()函数中的mt参数是否是对容器中对象的引用,还是可能隐藏的副本。使用ref(_1)可以避免这样的复制。我的答案试图表明,没有_placeholdered_对象的隐藏副本。 - rodrigo
关于“由于 _1 不是实际值”,措辞可以改进,因为这些占位符不是核心语言特性:它们是库解决方案,因此非常真实。只是 bind 特殊处理相应的类型。藏在 std::ref 的结果中,它不被该机制看到。 - Cheers and hth. - Alf
@Cheersandhth.-Alf:当然_1是一个值。只是它不是传递给dump()的值,这就是我所说的“真实”意义。我已经重新描述了一下,希望现在更清晰了。 - rodrigo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接