Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Revert is_assignable_without_narrowing related change
  • Loading branch information
yaito3014 committed Mar 12, 2026
commit 8a4f0528f463497fd7fb2a75f11e9ebe63ac3db2
23 changes: 0 additions & 23 deletions include/iris/type_traits.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -241,29 +241,6 @@ template<class From, class To>
inline constexpr bool is_convertible_without_narrowing_v = is_convertible_without_narrowing<From, To>::value;


// is_assignable_without_narrowing<Dest, Source>
//
// True when `Dest = Source` is valid AND does not involve a narrowing conversion.
//
// The arithmetic guard is intentional: narrowing conversions are only defined for
// arithmetic types ([dcl.init.list]), and the underlying `is_convertible_without_narrowing`
// uses brace-initialization (`To[]{from}`) which may select a different construction
// path than what `is_assignable` tests (e.g. initializer_list hijacking). Restricting
// the narrowing check to arithmetic Dest avoids false rejections for non-arithmetic
// types where the brace-init semantics diverge from assignment semantics.
template<class Dest, class Source>
struct is_assignable_without_narrowing
: std::bool_constant<
std::is_assignable_v<Dest, Source> &&
(!std::is_arithmetic_v<std::remove_reference_t<Dest>> ||
is_convertible_without_narrowing_v<std::remove_cvref_t<Source>, std::remove_reference_t<Dest>>)
>
{};

template<class Dest, class Source>
inline constexpr bool is_assignable_without_narrowing_v = is_assignable_without_narrowing<Dest, Source>::value;


namespace detail {

template<std::size_t I, class Ti>
Expand Down
44 changes: 0 additions & 44 deletions test/type_traits.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,50 +137,6 @@ TEST_CASE("is_convertible_without_narrowing")
}


TEST_CASE("is_assignable_without_narrowing")
{
// Non-narrowing: same type
STATIC_CHECK(iris::is_assignable_without_narrowing_v<int&, int>);
STATIC_CHECK(iris::is_assignable_without_narrowing_v<double&, double>);

// Non-narrowing: widening
STATIC_CHECK(iris::is_assignable_without_narrowing_v<long long&, int>);
STATIC_CHECK(iris::is_assignable_without_narrowing_v<double&, float>);
STATIC_CHECK(iris::is_assignable_without_narrowing_v<int&, short>);

// Narrowing: lossy conversions
STATIC_CHECK(!iris::is_assignable_without_narrowing_v<int&, long long>);
STATIC_CHECK(!iris::is_assignable_without_narrowing_v<short&, int>);
STATIC_CHECK(!iris::is_assignable_without_narrowing_v<float&, double>);
STATIC_CHECK(!iris::is_assignable_without_narrowing_v<int&, float>);
STATIC_CHECK(!iris::is_assignable_without_narrowing_v<float&, int>);

// Signed/unsigned mismatch
STATIC_CHECK(!iris::is_assignable_without_narrowing_v<int&, unsigned>);
STATIC_CHECK(!iris::is_assignable_without_narrowing_v<unsigned&, int>);

// Non-arithmetic dest: narrowing not checked (trusts user-defined conversion)
STATIC_CHECK(iris::is_assignable_without_narrowing_v<std::string&, const char*>);
STATIC_CHECK(iris::is_assignable_without_narrowing_v<convertible_from_int&, int>);

// Not assignable at all
STATIC_CHECK(!iris::is_assignable_without_narrowing_v<not_convertible_from_int&, int>);
STATIC_CHECK(!iris::is_assignable_without_narrowing_v<int&, std::string>);

// Non-arithmetic dest with explicit ctor + assignment operator.
// Without the arithmetic guard, is_assignable_without_narrowing would
// incorrectly return false because is_convertible_without_narrowing
// rejects explicit conversions (brace-init uses copy-list-init).
STATIC_CHECK(std::is_assignable_v<explicit_from_int&, int>);
STATIC_CHECK(!iris::is_convertible_without_narrowing_v<int, explicit_from_int>);
STATIC_CHECK(iris::is_assignable_without_narrowing_v<explicit_from_int&, int>);

// Verify the "false" implementation (without arithmetic guard) breaks here:
// it incorrectly rejects this valid, non-narrowing assignment.
STATIC_CHECK(!broken_is_assignable_without_narrowing<explicit_from_int&, int>::value);
}


TEST_CASE("specialization_of")
{
STATIC_CHECK(iris::is_ttp_specialization_of_v<tuple<>, tuple>);
Expand Down
Loading