Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ Lambda捕获作为常量引用?_C++_C++11_Lambda_C++14_C++17 - Fatal编程技术网

C++ Lambda捕获作为常量引用?

C++ Lambda捕获作为常量引用?,c++,c++11,lambda,c++14,c++17,C++,C++11,Lambda,C++14,C++17,是否可以通过lambda表达式中的常量引用捕获 我希望下面标记的作业失败,例如: #include <cstdlib> #include <vector> #include <string> #include <algorithm> using namespace std; int main() { string strings[] = { "hello", "world" };

是否可以通过lambda表达式中的常量引用捕获

我希望下面标记的作业失败,例如:

#include <cstdlib>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;

int main()
{
    string strings[] = 
    {
        "hello",
        "world"
    };
    static const size_t num_strings = sizeof(strings)/sizeof(strings[0]);

    string best_string = "foo";

    for_each( &strings[0], &strings[num_strings], [&best_string](const string& s)
      {
        best_string = s; // this should fail
      }
    );
    return 0;
}
#包括
#包括
#包括
#包括
使用名称空间std;
int main()
{
字符串[]=
{
“你好”,
“世界”
};
静态常量size_t num_strings=sizeof(strings)/sizeof(strings[0]);
字符串最佳\u string=“foo”;
对于每个字符串(&strings[0],&strings[num\u strings],&best\u string](常量字符串&s)
{
best_string=s;//这应该失败
}
);
返回0;
}

更新:因为这是一个老问题,如果C++14中有工具可以帮助解决这个问题,那么最好更新它。C++14中的扩展是否允许我们通过常量引用捕获非常量对象?(2015年8月)

const
不在n3092的捕获语法中:

capture:
  identifier
  & identifier
  this
本文仅提及通过复制和引用捕获,未提及任何类型的常量


对我来说这是一个疏忽,但我没有严格遵循标准化过程。

我想如果您没有使用变量作为functor的参数,那么您应该使用当前函数的访问级别。如果您认为不应该,那么将lambda与此函数分开,它不是它的一部分

无论如何,通过使用另一个常量引用,您可以轻松实现所需的相同功能:

#include <cstdlib>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;

int main()
{
    string strings[] = 
    {
        "hello",
        "world"
    };
    static const size_t num_strings = sizeof(strings)/sizeof(strings[0]);

    string best_string = "foo";
    const string& string_processed = best_string;

    for_each( &strings[0], &strings[num_strings], [&string_processed]  (const string& s)  -> void 
    {
        string_processed = s;    // this should fail
    }
    );
    return 0;
}
#包括
#包括
#包括
#包括
使用名称空间std;
int main()
{
字符串[]=
{
“你好”,
“世界”
};
静态常量size_t num_strings=sizeof(strings)/sizeof(strings[0]);
字符串最佳\u string=“foo”;
常量字符串&string\u processed=最佳字符串;
对于每个字符串(&strings[0],&strings[num\u strings],&string\u processed](常量字符串&s)->void
{
string_processed=s;//这应该失败
}
);
返回0;
}

但这与假设lambda必须与当前函数隔离,使其成为非lambda是一样的。

我认为您有三种不同的选择:

  • 不要使用常量引用,而是使用副本捕获
  • 忽略它是可修改的这一事实
  • 使用std::bind绑定具有常量引用的二进制函数的一个参数
使用副本 有拷贝捕获的lambda的有趣之处在于,它们实际上是只读的,因此可以完全按照您的要求执行

int main() {
  int a = 5;
  [a](){ a = 7; }(); // Compiler error!
}
使用std::bind
std::bind
减少函数的算术性。但是请注意,这可能/将导致通过函数指针进行间接函数调用

int main() {
  int a = 5;
  std::function<int ()> f2 = std::bind( [](const int &a){return a;}, a);
}
intmain(){
INTA=5;
std::function f2=std::bind([](const int&a){return a;},a);
}

我认为捕获部分不应该指定
const
,因为捕获意味着,它只需要一种访问外部范围变量的方法

最好在外部范围中指定说明符

const string better_string = "XXX";
[&better_string](string s) {
    better_string = s;    // error: read-only area.
}
lambda函数是常量(不能在其范围内更改值),因此当您按值捕获变量时,变量不能更改,但引用不在lambda范围内

在使用中/:


使用叮当声或等待此gcc错误修复:
bug 70385:通过const reference的引用捕获Lambda失败[]

还有一个较短的方法

请注意,在“best_string”之前没有“and”符号

它将是“const std::reference_wrapper>”类型


使用常量只需使用算法符号并将字符串设置为其原始值, 换句话说,lambda不会真正将自己定义为函数的参数,尽管周围的作用域将有一个额外的变量。。。 但是,如果不定义它,它就不会将字符串定义为典型的 [&,&best_string](字符串常量)
因此,我们最好还是保持这个状态,尝试捕获引用。

capture子句仍然只提到
best\u string
。除此之外,GCC4.5“成功地拒绝”了预期的代码。是的,这将给我带来我试图在技术层面上实现的结果。但最终,我最初问题的答案似乎是“否”。为什么这会使它成为“非lambda”?因为lambda的本质是它依赖于上下文。如果您不需要特定的上下文,那么这只是一种快速生成函子的方法。如果函子应该是上下文无关的,则将其设置为实函子。“如果函子应该是上下文无关的,则将其设置为实函子”。。。和可能的内联吻别?你的lambda不应该看起来像:
[&,&best_string](string const){…}
?真的不一致。“const&”在具有大的const对象时非常有用,应该在lambda函数中访问该对象,但不应在查看代码时对其进行修改。可以使用双参数lambda并将第二个参数绑定为常量引用。但这是有代价的。这在C++11中似乎是不可能的。但也许我们可以为C++14更新这个问题——是否有允许这样做的扩展?C++14广义lambda捕获?我刚刚跟踪了一个bug,找到了一个从捕获中修改的变量,该变量是可变的,但应该是
const
。或者更准确地说,如果捕获变量是
const
,编译器会在程序员身上强制执行正确的行为。如果语法支持
[&mutableVar,const&constVar]
,那就太好了。似乎这在C++14中是可能的,但我无法让它工作。有什么建议吗?常量是从捕获的变量继承的。因此,如果要将
a
捕获为
const
,请声明
const auto&b=a在lambda之前并捕获
b
@StenSoft Bleargh。除非显然这在通过引用捕获成员变量时不适用:
[&foo=this->foo]
函数中的
const
给了我一个错误
[&best_string = static_cast<const std::string&>(best_string)](const string& s)
{
    best_string = s; // fails
};
[&best_string = std::as_const(best_string)](const string& s)
{
    best_string = s; // fails
};
[best_string = cref(best_string)](const string& s)
{
    best_string = s; // fails
};