Skip to content

Commit

Permalink
New concept: reference_constructible_from_temporary
Browse files Browse the repository at this point in the history
  • Loading branch information
vector-of-bool committed Apr 1, 2024
1 parent c336345 commit b24f674
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 0 deletions.
27 changes: 27 additions & 0 deletions src/neo/concepts.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -515,4 +515,31 @@ concept non_narrowing_convertible_to =

// clang-format on

namespace detail {

template <typename Reference, typename From>
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<From>, add_pointer_t<Reference>>
// If we can convert to the reference' value type, then a conversion might occur
and constructible_from<remove_cvref_t<Reference>, 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<Reference, add_rvalue_reference_t<remove_cvref_t<Reference>>>;

} // namespace detail

#if NEO_HAS_BUILTIN(__reference_constructs_from_temporary)
template <typename Reference, typename From>
concept reference_constructible_from_temporary
= __reference_constructs_from_temporary(Reference, From);
#else
template <typename Reference, typename From>
concept reference_constructible_from_temporary //
= reference_type<Reference> //
and constructible_from<Reference, From> //
and detail::best_guest_ref_from_tmp<Reference, From>;
#endif

} // namespace neo
13 changes: 13 additions & 0 deletions src/neo/concepts.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,3 +187,16 @@ static_assert(not non_narrowing_convertible_to<signed, unsigned>);
static_assert(non_narrowing_convertible_to<unsigned short, signed int>);

static_assert(destructible<int&>);

TEST_CASE("reference_constructible_from_temporary") {
STATIC_REQUIRE(not reference_constructible_from_temporary<int, int>);
STATIC_REQUIRE(not reference_constructible_from_temporary<int&, int>);
STATIC_REQUIRE(not reference_constructible_from_temporary<int&, int&>);
STATIC_REQUIRE(not reference_constructible_from_temporary<int&, const int&>);
STATIC_REQUIRE(not reference_constructible_from_temporary<const int&, const int&>);
STATIC_REQUIRE(reference_constructible_from_temporary<const int&, const long&>);
STATIC_REQUIRE(reference_constructible_from_temporary<const std::string&, const char*>);
STATIC_REQUIRE(reference_constructible_from_temporary<std::string&&, const char*>);
STATIC_REQUIRE(not reference_constructible_from_temporary<std::string&, const char*>);
STATIC_REQUIRE(not reference_constructible_from_temporary<std::string, const char*>);
}

0 comments on commit b24f674

Please sign in to comment.