英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论