diff --git a/src/neo/concepts.hpp b/src/neo/concepts.hpp index 1a90ebe..fed9f00 100644 --- a/src/neo/concepts.hpp +++ b/src/neo/concepts.hpp @@ -515,4 +515,31 @@ concept non_narrowing_convertible_to = // clang-format on +namespace detail { + +template +concept best_guest_ref_from_tmp = + // If we can convert From* to Reference*, then there's a safe derived->base conversion + // that will not create a temporary + not convertible_to, add_pointer_t> + // If we can convert to the reference' value type, then a conversion might occur + and constructible_from, From> + // And if a reference can bind to an rvalue of the value type, then that's going to + // be the temporary binding we want to avoid + and constructible_from>>; + +} // namespace detail + +#if NEO_HAS_BUILTIN(__reference_constructs_from_temporary) +template +concept reference_constructible_from_temporary + = __reference_constructs_from_temporary(Reference, From); +#else +template +concept reference_constructible_from_temporary // + = reference_type // + and constructible_from // + and detail::best_guest_ref_from_tmp; +#endif + } // namespace neo diff --git a/src/neo/concepts.test.cpp b/src/neo/concepts.test.cpp index 90a0ad2..00e61ca 100644 --- a/src/neo/concepts.test.cpp +++ b/src/neo/concepts.test.cpp @@ -187,3 +187,16 @@ static_assert(not non_narrowing_convertible_to); static_assert(non_narrowing_convertible_to); static_assert(destructible); + +TEST_CASE("reference_constructible_from_temporary") { + STATIC_REQUIRE(not reference_constructible_from_temporary); + STATIC_REQUIRE(not reference_constructible_from_temporary); + STATIC_REQUIRE(not reference_constructible_from_temporary); + STATIC_REQUIRE(not reference_constructible_from_temporary); + STATIC_REQUIRE(not reference_constructible_from_temporary); + STATIC_REQUIRE(reference_constructible_from_temporary); + STATIC_REQUIRE(reference_constructible_from_temporary); + STATIC_REQUIRE(reference_constructible_from_temporary); + STATIC_REQUIRE(not reference_constructible_from_temporary); + STATIC_REQUIRE(not reference_constructible_from_temporary); +}