C++ 使用std::sregx\u令牌\u迭代器的std::transform的lambda(参数)中的常量限定符
我回答了一个关于SO的问题,以便解析一些字符串并生成特定的输出。为此,我使用了std::transform。对于一元运算,我使用了lambda。lambda的参数显然需要是常量。强迫我引入一个额外的局部变量。如果不使用const,我会得到一个语法错误编译器:MS VS19 我查看了CPPPreference上的std::transorm文档 一元运算-将应用的一元运算函数对象 函数的签名应等同于以下内容: Ret functonst类型&a 签名不需要有常量&。 类型必须使InputIt类型的对象可以被取消引用,然后隐式转换为类型。Ret类型必须使OutputIt类型的对象可以取消引用并分配Ret类型的值。 我不完全理解这一点。是否需要使用常量和参数。这是std::sregex_令牌_迭代器实现的结果吗?我试图理解的文件。抱歉,我无法理解是否可以将取消引用此迭代器转换为std::字符串 我走错方向了吗?或者有人能解释一下为什么它会这样?还是有我看不到的解决办法 示例代码:C++ 使用std::sregx\u令牌\u迭代器的std::transform的lambda(参数)中的常量限定符,c++,algorithm,lambda,iterator,C++,Algorithm,Lambda,Iterator,我回答了一个关于SO的问题,以便解析一些字符串并生成特定的输出。为此,我使用了std::transform。对于一元运算,我使用了lambda。lambda的参数显然需要是常量。强迫我引入一个额外的局部变量。如果不使用const,我会得到一个语法错误编译器:MS VS19 我查看了CPPPreference上的std::transorm文档 一元运算-将应用的一元运算函数对象 函数的签名应等同于以下内容: Ret functonst类型&a 签名不需要有常量&。 类型必须使InputIt类型的对
#include <string>
#include <iostream>
#include <regex>
#include <iterator>
int main()
{
// 1. This is the string to convert
std::string line("Hi there buddy");
// 2. We want to search for complete words
std::regex word("(\\w+)");
// 3. Transform the input string to output lines
std::transform(
std::sregex_token_iterator(line.begin(), line.end(), word, 1),
std::sregex_token_iterator(),
std::ostream_iterator<std::string>(std::cout, "\n"),
[](const std::string & w) { // ******* Must be const *******
static int i = 1;
std::string s = w;
s[0] = ::toupper(s[0]);
return std::string("List[") + std::to_string(i++) + "]=" + s;
}
);
return 0;
}
是否需要使用常量和参数
你不需要一个,但拥有一个通常是有意义的。首先,考虑到std::transform要求一元运算没有任何副作用。这意味着您无论如何都不允许更改参数。接下来,请注意,一元_op的参数是未引用的输入迭代器,如您所知。这可以是左值,也可以是右值,具体取决于传递给std::transform的输入序列。在您的例子中,取消引用std::regex_令牌迭代器会产生一个std::sub_匹配,它有一个到底层字符串类型的隐式转换运算符,对于您来说,它也是std::string。现在这是一个右值,右值只能绑定到一个const限定引用这就是为什么删除const并保留引用不会编译的原因。你还有另一个理由来设置常数
总之,您有以下选项:
通过常量引用传递。这应该是使用std::transform时的默认设置。
按值传递。如果要更改输入序列的副本以进行进一步处理,请执行此操作。这不会导致副作用,因此是允许的。
如果取消对迭代器的引用会产生一个临时值,那么您还可以在本例中传递一个右值引用std::string&&。修改或从中移动是合法的,因为这不会影响std::transform输入序列,而只影响临时输入序列。
在您的情况下,我将通过值传递并删除std::string w=v的副本。这将构造lambda操作的std::string对象,无副本
是否需要使用常量和参数
你不需要一个,但拥有一个通常是有意义的。首先,考虑到std::transform要求一元运算没有任何副作用。这意味着您无论如何都不允许更改参数。接下来,请注意,一元_op的参数是未引用的输入迭代器,如您所知。这可以是左值,也可以是右值,具体取决于传递给std::transform的输入序列。在您的例子中,取消引用std::regex_令牌迭代器会产生一个std::sub_匹配,它有一个到底层字符串类型的隐式转换运算符,对于您来说,它也是std::string。现在这是一个右值,右值只能绑定到一个const限定引用这就是为什么删除const并保留引用不会编译的原因。你还有另一个理由来设置常数
总之,您有以下选项:
通过常量引用传递。这应该是使用std::transform时的默认设置。
按值传递。如果要更改输入序列的副本以进行进一步处理,请执行此操作。这不会导致副作用,因此是允许的。
如果取消对迭代器的引用会产生一个临时值,那么您还可以在本例中传递一个右值引用std::string&&。修改或从中移动是合法的,因为这不会影响std::transform输入序列,而只影响临时输入序列。
在您的情况下,我将通过值传递并删除std::string w=v的副本。这将构造lambda操作的std::string对象,无副本
我不完全理解这一点。是否需要使用常量和参数
关键是不应该对输入迭代器指向的值进行变异,而应该从中读取。它是一个输入迭代器,而不是一个输出迭代器
正如您链接的文档所示:
一元运算和二元运算不能有副作用
改变输入将被视为副作用。接线员是
应该接受旧值并返回新值,而不是其他值
是否需要使用常量和参数
不,但你不允许改变原始对象。文件明确指出
签名不需要有常量&。
类型必须使InputIt类型的对象可以被取消引用,然后隐式转换为类型
所以,你可以采取隐式复制
[](std::string s) { /* no need to copy from w explicitly */ }
或者取一个from std::string
我不完全理解这一点。是否需要使用常量和参数
关键是不应该对输入迭代器指向的值进行变异,而应该从中读取。它是一个输入迭代器,而不是一个输出迭代器
正如您链接的文档所示:
一元运算和二元运算不能有副作用
改变输入将被视为副作用。运算符应该接受旧值并返回新值,而不是其他值
是否需要使用常量和参数
不,但你不允许改变原始对象。文件明确指出
签名不需要有常量&。
类型必须使InputIt类型的对象可以被取消引用,然后隐式转换为类型
所以,你可以采取隐式复制
[](std::string s) { /* no need to copy from w explicitly */ }
或者取一个from std::string
如果你不把它标记为const就不行了,只要你不修改它,但它确实应该是const,因为你无论如何都不会修改它。我想修改它。首字母大写。所以,我介绍了一个临时的。这是我想避免的。我是说,你不能修改w。复制它,然后修改副本并不算修改参数。如果不将其标记为常量(只要不实际修改它),则不可以,但它实际上应该是常量,因为您无论如何都不会修改它。我想修改它。首字母大写。所以,我介绍了一个临时的。这是我想避免的。我是说,你不能修改w。复制它然后修改副本并不算修改参数。输入迭代器。这是重点。这就是为什么。我习惯于在lambdas中引用参数,所以我没有采用传递值解决方案。难以置信的输入迭代器。这是重点。这就是为什么。我习惯于在lambdas中引用参数,所以我没有采用传递值解决方案。难以置信的anxSide效应和传递值。Than x。你和用户给了一个很好的解释。副作用和传递值。Than x。你和用户给了一个很好的解释。二者都