代码之家  ›  专栏  ›  技术社区  ›  Brandon

循环中使用“break”或“return”迭代元组

  •  0
  • Brandon  · 技术社区  · 2 年前

    我有一个元组 Args 由函数签名生成。 我想迭代元组,检查参数是否是特定类型,如果不是,则返回一个字符串。

    所以我想出了以下代码:

    std::tuple<Args...> arguments;
    Object* runtime_arguments = new Object[N];
    fill_args(runtime_arguments, N);
    
    auto is_valid_arguments = std::apply([&runtime_arguments](auto... arguments) {
        std::size_t i = 0;
        for (auto arg : {arguments...}) // Works only if `args` is homogenous.
        {
            std::string error;
            if (!is_valid_type<decltype(arg)>(runtime_arguments[i++], error))
            {
                return false;
            }
        }
        return true;
    }, arguments);
    
    template<typename T>
    bool is_valid_type(Object* object, std::string& error)
    {
        if constexpr(std::is_same<T, std::int32_t>::value)
        {
            return object->is_type('I');
        }
        else
        {
            static_assert(!is_native_type<T>::value, "Invalid Type");
        }
        return false;
    }
    

    我可以在编译时进行,但它会返回布尔值和错误字符串的元组,我不希望这样。我希望它打破循环,并在出现如上所示的问题时立即返回。

    如果 std::initializer_list<auto>{arguments...} 是同构的,因此如果元组是: std::tuple<Element*, char, bool> 它当然不会编译。

    有没有办法在元组中的元素上循环,并在第一个问题上中断? 也许是这样的:

    for_each(tuple, [](auto& e) {
        return true; // continues looping?
        return false; //stops the loop
    });
    

    所以我想到了这样的事情:

    template<size_t I = 0, typename Fn, typename... Tp>
    void for_each(std::tuple<Tp...>&& t, Fn &&fn) 
    {
        if (!fn(std::get<I>(t)) {
            return false;
        }
    
        if constexpr(I+1 != sizeof...(Tp)) {
            return for_each<I+1>(std::forward<std::tuple<Tp...>>(t), std::forward<Fn>(fn));
        }
    }
    

    有没有更好的方法来做到这一点或类似的事情(最好不要递归)?

    0 回复  |  直到 2 年前
        1
  •  2
  •   Artyer    2 年前

    折叠短路操作器(在这种情况下, && ):

    bool is_valid_arguments = std::apply([&runtime_arguments](auto... arguments) {
        std::size_t i = 0;
        return ([&]{
            std::string error;
            return is_valid_type<decltype(arguments)>(runtime_arguments[i++], error);
        }() && ...);
    }, arguments);
    

    您请求的 for_each 函数可以这样写:

    template<typename Tuple, typename F>
    void for_each(Tuple&& tuple, F&& f) {
        return std::apply(std::forward<Tuple>(tuple), [&f](auto&&... args) {
            return (f(std::forward<decltype(args)>(args)) && ...);
        });
    }