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 | |
} |