【问题标题】:lambda function capture and modify own referencelambda 函数捕获和修改自己的引用
【发布时间】:2017-07-07 17:30:19
【问题描述】:

有时需要执行一次特定功能,然后切换到另一个实现。

例如,流输出迭代器结合复制算法在打印项目后打印分隔符,这让我非常恼火:

> 1,2,3,4,
         ^---- this is what happens in that case

问题不在于很好地打印项目,而在于正确连接它们。

例如 Python 使用 string.join 函数产生正确的结果:

','.join((1,2,3,4))
> 1,2,3,4

我也想避免if/else 语句,因为我们只需要在第一次执行后进行一次切换。所以我想出的是:

std::function<char const*()> get_delim;

get_delim = [&get_delim]()
{
  get_delim = [](){ return ","; };
  return "";
};

for(auto b : some_byte_range)
  std::cout << get_delim() << b;

注意b 在我的例子中只是一个字节,这就是我没有使用auto const&amp; 的原因。

现在问题:

  • 有没有办法摆脱之前的std::function&lt;char const*()&gt; 声明并以某种方式声明get_delimauto,这实际上涉及到lambda 的自我捕获?
  • 是否有另一种更具表现力的方式(如在 Python 中)来实现这种join

【问题讨论】:

  • 我认为this question关于逗号分隔输出有一些有趣的想法
  • 您将无法使用auto,因为 lambda 类型是唯一的(您将无法为此类变量分配不同的 lambda)。但为什么是 lambda?这是一个很好的技巧,但您也可以编写一个简单的函数,使用带有 if 或类似内容的普通循环构造所需的字符串。

标签: c++ c++11 lambda c++14


【解决方案1】:

在这种情况下,您只需要:

auto get_delim = [c=char(0)]() mutable {
    char cur = c;
    c = ',';
    return cur;
};

甚至:

auto get_delim = [c=char(0)]() mutable { return std::exchange(c, ','); }

如果您愿意,也可以使用""",",应该很容易看出如何调整它以满足您的需要。


就图书馆而言,有一个std::experimental::ostream_joiner

【讨论】:

  • 但是每次调用get_delim 时都会执行std::exchange 吗?
  • @ovanes 分配一个字符非常便宜。
  • 嗯,我知道... :) 我只是想了解所涉及的内容...
  • 但我喜欢你的解决方案 :) 它非常优雅(第二个单线提案)。我知道 ostream_joiner,但它现在不是标准库的一部分:(
  • auto get_delim = [first=true]() mutable { return first ? first = false, "" : ","; } 虽然条件分支可能与交换一样昂贵。
猜你喜欢
  • 1970-01-01
  • 2018-01-22
  • 2012-11-07
  • 2020-08-19
  • 2020-01-15
  • 2013-07-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多