C ++ 17结构化绑定,还包括一个现有变量 [英] C++17 structured binding that also includes an existing variable

查看:90
本文介绍了C ++ 17结构化绑定,还包括一个现有变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此SO答案列出了C ++ 17分解声明的某些缺点(该功能以前称为结构化绑定 )。例如,您不能为新变量指定显式类型,依此类推。但是这里没有提到我遇到的一个大缺点,所以我想知道是否有一个我没有想到的已知解决方法。

This SO answer lists some shortcomings of C++17 decomposition declarations (the feature formerly known as "structured binding"). For example, you can't give explicit types to the new variables, and so on. But one big shortcoming I'm running into isn't mentioned there, so I wonder if there's a known workaround that I'm just not thinking of.

考虑此JSON解析代码(其中可能包含其他错误;出于本问题的目的,请忽略它们):

Consider this JSON-parsing code (which may contain other bugs; please ignore them for the purposes of this question):

using Value = std::any;
using String = std::string;
using Object = std::map<String, Value>;

std::pair<String, const char *> load_string(const char *p, const char *end);
std::pair<Value, const char *> load_value(const char *p, const char *end);
const char *skip_spaces(const char *p, const char *end);

std::pair<Object, const char *> load_object(const char *p, const char *end)
{
    p = skip_spaces(p, end);
    if (p == end || *p++ != '{') throw ParseError("Expected {");
    p = skip_spaces(p, end);
    Object result;
    if (p == end && *p == '}') {
        // the object has no key-value pairs at all
    } else {
        while (true) {
            auto [key, p] = load_string(p, end);
            p = skip_spaces(p, end);
            if (p == end || *p++ != ':') throw ParseError("Expected :");
            auto [value, p] = load_value(p, end);
            result.insert_or_assign(std::move(key), std::move(value));
            p = skip_spaces(p, end);
            if (p == end) throw ParseError("Expected , or }");
            if (*p == '}') break;
            if (*p++ != ',') throw ParseError("Expected , or }");
        }
    }
    return {result, p+1};
}

这会很好用,除了以开头的行auto [key,p] = auto [value,p] = 无效!变量 p 已被声明。我正在尝试为 p 分配新的,但是我不想创建一个全新的局部变量

This would work great, except that the lines starting auto [key, p] = and auto [value, p] = are invalid! The variable p has already been declared. I'm trying to assign p a new value, but I don't want to create a whole new local variable.

我不想使用 std :: tie(key,p)= ,因为这需要我要在作业前声明 key 。这是对 std :: tie 的熟悉的反对意见。我可能发誓是将结构化绑定引入语言的原因!

I would prefer not to use std::tie(key, p) =, because that requires me to give a declaration for key before the assignment. This is the familiar old objection to std::tie. Which I could have sworn was the reason structured binding was introduced into the language!

那么有什么解决方法吗?-编写组合构造的任何好方法-密钥就位并还分配给表达我意图 p

So is there any workaround — any nice clean way of writing the combination construct-key-in-place-and-also-assign-to-p that expresses my intention?

奇怪的是,我以前从未错过过此功能,但是一旦您给我提供结构化绑定来使用,我尝试的第一件事就不起作用了。 :(

It's strange how I never missed this feature before, but as soon as you give me structured binding to play with, the first thing I try doesn't work. :(

推荐答案

这是一个非常愚蠢的想法,除非最终出现 no 合理的解决方法...但请考虑以下代码。

This is a really dumb idea that I wouldn't seriously suggest unless there ends up being no sane workaround... but consider the following code.

template<size_t P, size_t... Is>
auto plus(std::index_sequence<Is...>)
{
    return std::index_sequence<P+Is...>{};
}

template<typename RHS, size_t... Is>
auto tuple_select(RHS&& rhs, std::index_sequence<Is...>)
{
    return std::forward_as_tuple(std::get<Is>(std::forward<RHS>(rhs))...);
}

template<typename... Ts>
struct AndTie {
    std::tuple<Ts&...> v;
    AndTie(Ts&... vs) : v(vs...) {}

    template<typename RHS>
    auto operator=(RHS&& rhs) && {
        constexpr int N = std::tuple_size_v<RHS>;
        constexpr int K = sizeof...(Ts);
        v = tuple_select(std::forward<RHS>(rhs), plus<N-K>(std::make_index_sequence<K>{}));
        return tuple_select(std::forward<RHS>(rhs), std::make_index_sequence<N-K>{});
    }
};

这给了我们

auto [key] =AndTie(p)= load_string(p, end);
auto [value] =AndTie(p)= load_value(p, end);

它仍然有一个局限性,即并列左值必须限制在最后出现和声明的变量被约束为首先出现 ,但是我认为没有很多方法可以解决此问题。像 tuple_shuffle< Is ...> 之类的东西可以在需要时进行处理。

It still has the limitation that the "tied" lvalues are constrained to appear last and the "declared" variables are constrained to appear first, but I don't think there's much way to get around that. And something like tuple_shuffle<Is...> could handle that if you needed it.

这篇关于C ++ 17结构化绑定,还包括一个现有变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆