Some solutions to declare a const ref parameter that does not bind to a temporary.
Compiler-explorer link https://gcc.godbolt.org/z/8Gohnc98f
Some solutions to declare a const ref parameter that does not bind to a temporary.
Compiler-explorer link https://gcc.godbolt.org/z/8Gohnc98f
| // problem: we want to pass a const reference, but we want to prevent temporary | |
| // to bind to it | |
| // a type and a subtype to run the tests | |
| struct type { | |
| int v; | |
| }; | |
| struct subtype : public type { | |
| int vv; | |
| }; | |
| // option 1: just delete it, does not scale well with the number of parameters | |
| void foo_explicit(type&&) = delete; | |
| void foo_explicit(type const& t) { auto v = t.v; }; | |
| // option 2: use a ref_wrap. requires functional, ugly use | |
| #include <functional> | |
| #include <type_traits> | |
| void foo_refwrap(std::reference_wrapper<const type> t) { auto v = t.get().v; } | |
| // option 3: write a dumbo ref_wrap (const). simpler than including functional? | |
| template <typename T> | |
| struct my_cref_wrap { | |
| const T& internal; | |
| constexpr my_cref_wrap(const T& v) noexcept : internal{v} {} | |
| my_cref_wrap(T&&) = delete; | |
| }; | |
| void foo_mycrefwrap(my_cref_wrap<type> t) { auto v = t.internal.v; } | |
| // option 4: a concept. it's like a wrapper, simpler(?) but it is template | |
| template <typename T, typename U> | |
| concept not_temp = std::derived_from<std::decay_t<T>, std::decay_t<U>> && | |
| (!std::is_rvalue_reference_v<U>); | |
| void foo_concept(not_temp<type> auto const& t) { auto v = t.v; } | |
| int main() { | |
| auto a = subtype{}; | |
| auto const ca = subtype{}; | |
| auto& ra = a; | |
| auto& cra = ca; | |
| foo_explicit(a); | |
| foo_explicit(ca); | |
| foo_explicit(ra); | |
| foo_explicit(cra); | |
| // foo_explicit(subtype{}); // error | |
| foo_refwrap(a); | |
| foo_refwrap(a); | |
| foo_refwrap(ra); | |
| foo_refwrap(cra); | |
| // foo_refwrap(subtype{}); // error | |
| foo_mycrefwrap(a); | |
| foo_mycrefwrap(a); | |
| foo_mycrefwrap(ra); | |
| foo_mycrefwrap(cra); | |
| // foo_mycrefwrap(subtype{}); // error | |
| foo_concept(a); | |
| foo_concept(a); | |
| foo_concept(ra); | |
| foo_concept(cra); | |
| // foo_concept(subtype{}); // error | |
| } |