【问题标题】:For loop for variable - value initialization变量值初始化的for循环
【发布时间】:2020-08-28 18:02:22
【问题描述】:

我受到@fredoverflow 这个问题的回答的启发:Multiple Counter Problem In For Loop

所以我有一堆变量和一堆值,我会传递抛出函数。例如:

 bool a, b, c;
 string string_a, string_b, string_c;
 a = foo(string_a);
 b = foo(string_b);
 c = foo(string_c);

我可以像这样创建for循环,而不是手动编写所有这些:

for (struct {bool boo; string str;} loop: {{a, string_a}, {b, string_b}, {c, string_c}}){
    loop.boo = foo(loop.str);
}

它看起来不像是变量赋值的合法方式,或者我在这里错过了几个符号? 这种技巧是否被认为是一种好习惯?

【问题讨论】:

  • 好的做法是编写清晰易读的代码。你可能有范围问题。
  • 只需在声明时一一分配布尔值。

标签: c++ for-loop


【解决方案1】:

std::transform 可能会有所帮助。

std::vector<string> src = {string_a, string_b, string_c};
std::vector<bool> dest(src.size());

std::transform(src.begin(), src.end(), dest.begin(), foo);

要让它修改变量,您可以使用std::for_each

std::vector<std::pair<bool*, string*> > targets = {{&a, &string_a}, {&b, &string_b}, {&c, &string_c}};
std::for_each(targets.begin(), targets.end(), [](auto& p){ *p.first = foo(*p.second); });

或者用for声明:

for(auto loop: std::vector<std::pair<bool*, string*> > {{&a, &string_a}, {&b, &string_b}, {&c, &string_c}}) {
    *loop.first = foo(*loop.second);
}

【讨论】:

  • 你在酒吧里写这个吗?
【解决方案2】:

将结构化绑定与基于范围的 for 循环与 (C++20) 初始化语句相结合

从 C++20 开始,您可以使用 range-based for loop 初始化语句,您可以将其与 structured bindings 组合如下:

#include <ios>
#include <iostream>
#include <string>
#include <string_view>
#include <utility>

bool foo(std::string_view s) {
    return s == "b";  
}

int main() {
    bool a{false}, b{false}, c{false};
    std::string string_a{"a"}, string_b{"b"}, string_c{"c"};
    
    for (typedef std::pair<bool&, std::string_view> P;
         auto [res, str] : {P{a, string_a}, {b, string_b}, {c, string_c}}) {
        res = foo(str);
    }
    
    std::cout << std::boolalpha << a << " " << b << " " << c << "\n";
        // false true false
}

利用typedef declarations are init-statements(其中没有alias-declarations)这一事实来声明P 实用程序别名,该别名又用于在初始化列表中进行类型推导基于 for 循环迭代(并绑定值)。

在 C++20 之前,您可以简单地将实用程序类型别名放在循环之前:

using P = std::pair<bool&, std::string_view>;
for (auto [res, str] : {P{a, string_a}, {b, string_b}, {c, string_c}}) {
    res = foo(str);
}

或完全删除实用程序类型别名:

for (auto [res, str] : {
        std::pair<bool&, std::string_view>{a, string_a},
        {b, string_b}, {c, string_c}}) {
    res = foo(str);
}

这样的技巧被认为是一种好的做法吗?

这部分答案可能会进入基于意见的领域,虽然这不一定适用于上面的 sn-p,但它肯定适用于使用的技术 in the answer you refer to ("Hckety hack hack")。句法组合非常聪明,以至于最终被称为“技巧”,可能最终过于聪明而对自己的利益不利,并且阻碍了代码库的清晰度和理解,对于特定的作者代码以及其他(当前和未来)维护者。

【讨论】:

    猜你喜欢
    • 2012-01-02
    • 1970-01-01
    • 2011-04-02
    • 1970-01-01
    • 1970-01-01
    • 2012-06-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多