Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/144.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+中的引用变量捕获的+;兰姆达? 我有这个C++函数对象: static unsigned long long const FNV_OFFSET_BASIS = 14695981039346656037ul; static unsigned long long const FNV_PRIME = 1099511628211ul; struct fnv_hash { typedef unsigned long long value_type; fnv_hash( value_type *result ) { _result = result; *_result = FNV_OFFSET_BASIS; } void operator()( char c ) { // Fowler–Noll–Vo FNV-1a hash function *_result ^= c; // see: https://en.wikipedia.org/wiki/Fowler–Noll–Vo_hash_function *_result *= FNV_PRIME; } private: value_type *_result; };_C++_Lambda - Fatal编程技术网

初始化由C+中的引用变量捕获的+;兰姆达? 我有这个C++函数对象: static unsigned long long const FNV_OFFSET_BASIS = 14695981039346656037ul; static unsigned long long const FNV_PRIME = 1099511628211ul; struct fnv_hash { typedef unsigned long long value_type; fnv_hash( value_type *result ) { _result = result; *_result = FNV_OFFSET_BASIS; } void operator()( char c ) { // Fowler–Noll–Vo FNV-1a hash function *_result ^= c; // see: https://en.wikipedia.org/wiki/Fowler–Noll–Vo_hash_function *_result *= FNV_PRIME; } private: value_type *_result; };

初始化由C+中的引用变量捕获的+;兰姆达? 我有这个C++函数对象: static unsigned long long const FNV_OFFSET_BASIS = 14695981039346656037ul; static unsigned long long const FNV_PRIME = 1099511628211ul; struct fnv_hash { typedef unsigned long long value_type; fnv_hash( value_type *result ) { _result = result; *_result = FNV_OFFSET_BASIS; } void operator()( char c ) { // Fowler–Noll–Vo FNV-1a hash function *_result ^= c; // see: https://en.wikipedia.org/wiki/Fowler–Noll–Vo_hash_function *_result *= FNV_PRIME; } private: value_type *_result; };,c++,lambda,C++,Lambda,可以像这样使用: std::string const message = "hello, world"; hash::value_type hash_val; std::for_each( message.begin(), message.end(), fnv_hash( &hash_val ) ); 如果我想将函数对象转换为lambda,那么只有在构建底层编译器生成的lambda对象时,才会将捕获的变量hash_val初始化为FNV_OFFSET_BASIS。我

可以像这样使用:

std::string const message = "hello, world";
hash::value_type hash_val;

std::for_each( message.begin(), message.end(), fnv_hash( &hash_val ) );
如果我想将函数对象转换为lambda,那么只有在构建底层编译器生成的lambda对象时,才会将捕获的变量
hash_val
初始化为
FNV_OFFSET_BASIS
。我唯一能想到的就是使用另一个lambda:

std::for_each( message.begin(), message.end(),
    [&hv = [&hash_val]() -> decltype((hash_val)) {
               return hash_val = FNV_OFFSET_BASIS;  // Initialize and return reference to hash_val.
            }()                                     // Call the inner lambda.
           ]( char c ) {
        hv ^= c;
        hv *= FNV_PRIME;
    }
);
这是可行的,但有没有更干净的方法


:给出的示例仅用于教学目的。问题的关键在于如何“初始化”一个lambda,而不是如何解决这个特殊的hash示例


注意:“做不到”是可以接受的答案。如果有人问我类似的问题,我需要一个答案:在什么情况下,我们仍然应该使用函数对象而不是lambda?

以牺牲一些效率为代价,您可以使用第二个传递值参数来初始化
hash\u val

std::for_each( message.begin(), message.end(),
    [&hash_val, initialised = false](char c) mutable {
        if (!initialised)
        {
            hash_val = FNV_OFFSET_BASIS;
            initialised = true;
        }
        hash_val ^= c;
        hash_val *= FNV_PRIME;
    }
);

但是我更喜欢函子。

你说你可以使用
std::acculate
这个事实只是为了这个特定的例子,但我对此表示怀疑。
std::for_each
std::acculate
之间唯一的真正区别在于
std::acculate
使状态显式,包括处理初始化。我认为这是所有情况下的解决办法

static unsigned long long const FNV_OFFSET_BASIS = 14695981039346656037ul;
static unsigned long long const FNV_PRIME        = 1099511628211ul;

struct fnv_hash {
    typedef unsigned long long value_type;
    value_type operator()(value_type _result, char c) {  // Fowler–Noll–Vo FNV-1a hash function
        _result ^= c;           //   see: https://en.wikipedia.org/wiki/Fowler–Noll–Vo_hash_function
        _result *= FNV_PRIME;
        return _result;
    }
};

int main() {
std::string const message = "hello, world";
fnv_hash::value_type hash_val 
    = std::accumulate( message.begin(), message.end(), FNV_OFFSET_BASIS, fnv_hash() );
}

accumulate
接受一个二进制运算符,但第一个参数是容器中的条目,第二个参数是您需要的任何状态:在您的例子中,它只是
value\u type\u result
。尽管这一概念毫无疑问地扩展到了任意状态

现在,用lambda替换它显然是微不足道的:

value_type hash_val = std::accumulate( message.begin(), message.end(), FNV_OFFSET_BASIS, 
    [](value_type _result, char c) {  // Fowler–Noll–Vo FNV-1a hash function
        _result ^= c;           //   see: https://en.wikipedia.org/wiki/Fowler–Noll–Vo_hash_function
        _result *= FNV_PRIME;
        return _result;
    });

在lambda捕获变量之前,只需在声明变量的位置初始化该变量。lambda无需对其进行初始化,只需对其进行变异,例如:

使用hash\u value\u type=unsigned long;
静态哈希值类型常量FNV偏移量基础=14695981039346656037ul;
静态哈希值类型常量FNV素数=109951162811ul;
std::string const message=“你好,世界”;
散列值类型散列值=FNV偏移量基础;
std::每个(
message.begin(),message.end(),
[&hash_val](字符c){
hash_val^=c;
hash_val*=FNV_素数;
}
);
或者,使用
std::accumulate()
而不是
std::for_each()
,这样您甚至不需要捕获
hash_val
变量,例如:

使用hash\u value\u type=unsigned long;
静态哈希值类型常量FNV偏移量基础=14695981039346656037ul;
静态哈希值类型常量FNV素数=109951162811ul;
std::string const message=“你好,世界”;
哈希值类型哈希值=标准::累加(
message.begin(),message.end(),
FNV_偏移量_基础,
[](哈希值类型值,字符c){
val^=c;
val*=FNV_素数;
返回val;
}
);

由于此时调用代码需要知道
FNV\u OFFSET\u基
无论如何,在将其传递给lambda之前初始化
hash\u val
不是最容易的吗?这看起来确实像是
std::acculate
的作业。..@igortandtnik最容易?大概但我更喜欢保证用户不会出错的代码。@MooingDuck可以将示例替换为lambda需要一些初始状态的其他示例。对于这个特定的示例,我是否可以使用
std::acculate
,这并不是问题的关键。您认为让用户编写两级lambda是一种改进吗?如果正确性是您的目标,为什么不保留命名的函数,
fnv\u hash
?因为它封装得很好,所以需要一些努力才能正确使用。@PaulJ.Lucas:我刚才注意到了。完成。我对原始代码运行了lambda版本,但结果并不相同(尽管我不清楚有什么不同)。@PaulJ.Lucas,这就是结果错误的原因。参数必须是
(值类型\u结果,字符c)
而不是
(字符c,值类型\u结果)
@RemyLebeau:Whoopsie!:(