C++ 使用std::sregx\u令牌\u迭代器的std::transform的lambda(参数)中的常量限定符

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类型的对

我回答了一个关于SO的问题,以便解析一些字符串并生成特定的输出。为此,我使用了std::transform。对于一元运算,我使用了lambda。lambda的参数显然需要是常量。强迫我引入一个额外的局部变量。如果不使用const,我会得到一个语法错误编译器:MS VS19

我查看了CPPPreference上的std::transorm文档

一元运算-将应用的一元运算函数对象

函数的签名应等同于以下内容:

Ret functonst类型&a

签名不需要有常量&。 类型必须使InputIt类型的对象可以被取消引用,然后隐式转换为类型。Ret类型必须使OutputIt类型的对象可以取消引用并分配Ret类型的值。​

我不完全理解这一点。是否需要使用常量和参数。这是std::sregex_令牌_迭代器实现的结果吗?我试图理解的文件。抱歉,我无法理解是否可以将取消引用此迭代器转换为std::字符串

我走错方向了吗?或者有人能解释一下为什么它会这样?还是有我看不到的解决办法

示例代码:

#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。你和用户给了一个很好的解释。二者都