英文:
Capture return value from fold expression in std::apply
问题
以下是您提供的代码的翻译部分:
我有一个简单的片段,试图说明我要做的事情。
我将几个类实例打包到一个元组中,并使用std::apply迭代它们。
我想捕获两个值:
- 如果找到匹配的键
- 如果找到键,返回
do_test
调用的结果
我将(2)捕获到变量fn_ret
中,但对于(1),我无法确定在迭代元组时是否找到了键。我认为在传递它到折叠表达式之前,我可能需要以某种方式存储/获取search_tuple(args)
的结果。我该如何操作?
#include <iostream>
#include <tuple>
using namespace std;
class foo
{
public:
foo(int i) : key_(i) {}
int get_key()
{
return key_;
}
int do_test()
{
std::cout << "ran test for key=" << key_ << "\n";
return -1;
}
private:
int key_;
};
int main()
{
std::tuple tup{foo{1}, foo{2}, foo{3}, foo{4}, foo{5}, foo{6}, foo{7}, foo{8}};
int key = 4;
int fn_ret = 0;
std::apply
(
[key, &fn_ret](auto&... args)
{
auto search_tuple = [key, &fn_ret](auto& x) {
int foo_key = x.get_key();
cout << "current key=" << foo_key << "\n";
if (foo_key == key)
{
std::cout << "found matching key, running test!\n";
fn_ret = x.do_test();
return 0;
}
return -1;
};
(search_tuple(args) && ...);
}, tup
);
return 0;
}
请注意,我已经进行了必要的代码格式化,以使其更具可读性。
英文:
I have a simple snippet that tries to illustrate what I'm trying to do.
I pack a few class instances in a tuple and iterate over them using std::apply.
I'd like to capture two values:
- If a matching key was found
- If a key was found, return the result of the
do_test
call
I capture (2) in a variable fn_ret
, but for (1), I can't tell if a key was found while iterating over the tuple. I think I might need to store/get the result of search_tuple(args)
somehow before passing it in the fold expression. How do I go about doing that?
#include <iostream>
#include <tuple>
using namespace std;
class foo
{
public:
foo(int i) : key_(i){}
int get_key()
{
return key_;
}
int do_test()
{
std::cout << "ran test for key=" << key_ << "\n";
return -1;
}
private:
int key_;
};
int main()
{
std::tuple tup { foo{1}, foo{2}, foo{3}, foo{4}, foo{5}, foo{6}, foo{7}, foo{8} };
int key = 4;
int fn_ret = 0;
std::apply
(
[key, &fn_ret](auto&... args)
{
auto search_tuple = [key, &fn_ret](auto& x) {
int foo_key = x.get_key();
cout << "current key=" << foo_key << "\n";
if (foo_key == key)
{
std::cout << "found matching key, running test!\n";
fn_ret = x.do_test();
return 0;
}
return -1;
};
(search_tuple(args) && ...);
}, tup
);
return 0;
}
答案1
得分: 2
以下是翻译好的部分:
以下的代码在相当程度上可以工作。 它在 `fn_ret` 中存储了一个特殊的初始值来检查是否找到了键。而不是从主函数一起传递一个额外的布尔变量通过引用传递 `key` 和 `fn_ret`。
#include <iostream>
#include <tuple>
using namespace std;
class foo
{
public:
foo(int i) : key_(i) {}
int get_key()
{
return key_;
}
int do_test()
{
std::cout << "ran test for key=" << key_ << "\n";
return key_ * key_; // 对键执行一些操作
}
private:
int key_;
};
int main()
{
std::tuple tup{foo{1}, foo{2}, foo{3}, foo{4}, foo{5}, foo{6}, foo{7}, foo{8}};
int key = 10;
int fn_ret = -1;
bool key_fnd = false;
std::apply
(
[key, &fn_ret, &key_fnd](auto&... args) {
auto search_tuple = [key, &fn_ret, &key_fnd](auto& x) {
int foo_key = x.get_key();
cout << "current key=" << foo_key << "\n";
if (foo_key == key)
{
std::cout << "found matching key, running test!\n";
key_fnd = true;
fn_ret = x.do_test();
return 0;
}
return -1;
};
(search_tuple(args) && ...);
}, tup
);
if (!key_fnd) {
std::cout<<"The key was not found"<<std::endl;
}
else {
std::cout<<"The result of running the test on key "<<key;
std::cout<<" is "<<fn_ret<<std::endl;
}
return 0;
}
根据康桓瑋的评论,可以将逻辑简化如下。请注意,折叠表达式应基于 ||
,以确保键与任何一个键匹配。此外,在找到匹配后,折叠表达式的评估将停止。
bool key_fnd = std::apply(
[key, &fn_ret](auto&... args) {
auto search_tuple = [key, &fn_ret](auto& x) {
int foo_key = x.get_key();
cout << "current key=" << foo_key << "\n";
if (foo_key == key) {
std::cout << "found matching key, running test!\n";
fn_ret = x.do_test();
return true;
}
return false;
};
return (search_tuple(args) || ...);
}, tup
);
英文:
The following code works to a reasonable extent. It stores a special initial value in fn_ret
to check whether the key was found. Instead an additional boolean variable could be passed by reference from main along with key
and fn_ret
.
#include <iostream>
#include <tuple>
using namespace std;
class foo
{
public:
foo(int i) : key_(i){}
int get_key()
{
return key_;
}
int do_test()
{
std::cout << "ran test for key=" << key_ << "\n";
return key_*key_; // Some operation on the key
}
private:
int key_;
};
int main()
{
std::tuple tup { foo{1}, foo{2}, foo{3}, foo{4}, foo{5}, foo{6}, foo{7}, foo{8} };
int key = 10;
int fn_ret = -1;
bool key_fnd = false;
std::apply
(
[key, &fn_ret, &key_fnd](auto&... args) {
auto search_tuple = [key, &fn_ret, &key_fnd](auto& x) {
int foo_key = x.get_key();
cout << "current key=" << foo_key << "\n";
if (foo_key == key)
{
std::cout << "found matching key, running test!\n";
key_fnd = true;
fn_ret = x.do_test();
return 0;
}
return -1;
};
(search_tuple(args) && ...);
}, tup
);
if (!key_fnd) {
std::cout<<"The key was not found"<<std::endl;
}
else {
std::cout<<"The result of running the test on key "<<key;
std::cout<<" is "<<fn_ret<<std::endl;
}
return 0;
}
As per 康桓瑋's comment, the logic can be simplified as shown below. Note, the fold expression should be based on ||
to ensure that the key matches with any one of the keys. Also, the evaluation of the fold expression stops when a match has been found.
bool key_fnd = std::apply(
[key, &fn_ret](auto&... args) {
auto search_tuple = [key, &fn_ret](auto& x) {
int foo_key = x.get_key();
cout << "current key=" << foo_key << "\n";
if (foo_key == key) {
std::cout << "found matching key, running test!\n";
fn_ret = x.do_test();
return true;
}
return false;
};
return (search_tuple(args) || ...);
}, tup
);
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论