As πάντα ῥεῖ
pointed out in the comments, if you require an lvalue then you should write your function that way (single &
):
[from your comment, I've used c++17 style]
template <typename Arg>
auto && just(Arg & arg);
However, I'll consider your real world problem isn't so simple and that you prefer to code the requirements inside the function:
#include <type_traits>
template <typename Arg>
auto && just(Arg && arg) {
static_assert(std::is_lvalue_reference_v<Arg&&>);
return std::forward<Arg>(arg);
}
Example: It's practical for a function to do some work then return the output of a function with perfect forwarding to avoid copies, but you need to check its return type. For those not able to use concepts
it's neater to do the check inside the function:
#include <iostream>
#include <type_traits>
template <typename Func>
auto && just (Func && func)
{
using return_type = decltype(func());
static_assert(std::is_reference_v<return_type>, "returning temportary");
// calculate arguments for func
// (no args here for simplicity)
return func(); // always return ref
}
int global;
int ReturnCopy () { return int(); }
int & ReturnGlobal () { return global; }
int && ReturnTemporary () { return std::move(global); }
int main ()
{
just(ReturnCopy); // <--- error
just(ReturnGlobal);
just(ReturnTemporary);
}
just(auto&& arg)
, um, what version of C++ are you using? That function shouldn't compile in c++11, 14, or 17 without-fconcepts
. - Elliottgcc-9.3
with-std=c++17 -fconcepts
- Vahagnjust<Something&&>(std::move(hold))
would compile, which I think wasn't what AndyG meant to do. It could've easily been fixed by changing it to something likerequires std::is_lvalue_reference_v<T>
, or more intuitivelyis_lvalue_reference_v<T&&>
. - Elliott