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 type
In cases with more complex types, a simple workaround of a movable temporary new object might be the simplest desirable step in the direction of what you want (though I reckon in your particular case it might be simpler to stick to traditional tie
instead):
... // (as in your code: p & end exist already, key & p_ not yet)
auto [key, p_] = load_string(p, end);
p = move(p_);
... // (continue using p)
I'm sorry I eventually couldn't compile it myself though I could see it being a problem of my IDE (CLion which currently only halfly supports C++17) though I'd expect it to work in general.
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>{});
}
};
This gives us
auto [key] =AndTie(p)= load_string(p, end);
auto [value] =AndTie(p)= load_value(p, end);
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.