英文:
C++20 Returning Non-type Variadic Template Tuple of References
问题
Currently using g++11.3.0, C++20.
This is a follow up from a previous query.
I have a function foo that takes an arbitrary number of template arguments and returns a tuple that contains a value for each template argument. However, the function currently returns a tuple of l-values. I would like to return a tuple of l-value references. I've tried changing the return type to std::tuple<Args&...> and using std::tie() instead of std::make_tuple(), but it gives me the error:
error: no matching function for call to 'tie'
The lambda in the function actually returns a non-local variable with the respective data type, so the line return Args(); is just there as a substitution to provide compilable code for this post.
template <typename ...Args>
std::tuple<Args...> foo()
{
    return std::make_tuple([] ()
    {
        // Do some stuff....
        // Return non-local l-value....
        return Args();
    }()...);
}
英文:
Currently using g++11.3.0, C++20.
This is a follow up from a previous query.
I have a function foo that takes an arbitrary number of template arguments and returns a tuple that contains a value for each template argument. However, the function currently returns a tuple of l-values. I would like to return a tuple of l-value references. I've tried changing the return type to std::tuple<Args&...> and using std::tie() instead of std::make_tuple(), but gives me the error:
error: no matching function for call to 'tie'
The lambda in the function actually returns a non-local variable with the respective data type, so the line return Args(); is just there as a substitution to provide compilable code for this post.
template <typename ...Args>
std::tuple<Args...> foo()
{
    return std::make_tuple([] ()
    {
        // Do some stuff....
        // Return non-local l-value....
        return Args();
    }()...);
}
答案1
得分: 1
不要有别的内容
英文:
A lambda without specified return value always returns by-value, not by-reference. Specifically it returns with a return type of auto by default. So your call to the lambda never produces a lvalue, always a prvalue. std::tie then fails, because it accepts only lvalues.
If you want to have the lambda return a lvalue reference, you need to specify its return type. I wouldn't make it specifically a lvalue reference though. You can have it deduce the appropriate value category automatically with decltype(auto):
[] () -> decltype(auto)
{
    // Do some stuff....
    // Return non-local l-value....
    return Args();
}()
(However, Args() is a prvalue, not a lvalue, so this will still deduce to a non-reference type. If you actually want to have the lambda return a lvalue reference, then actually give the return statement a lvalue as operand.)
Alternatively you can specify Args& as the return type of the lambda explicitly.
After that, you can use std::tie or alternatively std::forward_as_tuple. The latter will correctly deduce whether the references should be lvalue references or rvalue references automatically, while std::tie assumes lvalue references and will fail otherwise. Typically it is desirable that the value category is deduced, although in your situation it might be a potential source of error since it would have caused UB instead of a compilation error with your wrong return type on the lambda.
Then you can also use auto as return type for foo, so that the automatically deduced value category applies, but that is a matter of style.
On a side note, if your lambdas have side effects, note that the order in which the lambdas will be evaluated is indeterminate. You can not rely on any particular ordering.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论