Skip to content

Add is_convertible_without_narrowing#54

Open
yaito3014 wants to merge 17 commits intomainfrom
add-is-convertible-without-narrowing
Open

Add is_convertible_without_narrowing#54
yaito3014 wants to merge 17 commits intomainfrom
add-is-convertible-without-narrowing

Conversation

@yaito3014
Copy link
Member

@yaito3014 yaito3014 commented Mar 12, 2026

fixes #5

The array form To[] is specifically chosen over the simpler To{from} because the latter can accidentally select aggregate initialization of To itself (if To is an aggregate) or match a constructor taking std::initializer_list, both of
which would mask the actual narrowing behavior. Since To[] is always an aggregate regardless of what To is, the braced initialization applies uniformly to the element type and tests exactly what we want: whether From can be
copy-initialized into a To slot without narrowing.

@yaito3014 yaito3014 self-assigned this Mar 12, 2026
@yaito3014 yaito3014 added the enhancement New feature or request label Mar 12, 2026
@cppwarningnotifier
Copy link

EnvironmentC++23C++26
irisClang21Debug✅success✅success
Release✅success✅success
GCC14Debug✅success✅success
Release✅success✅success
MSVC2022Debug✅success✅success
Release✅success✅success
2026Debug✅success✅success
Release✅success✅success

@saki7
Copy link
Member

saki7 commented Mar 12, 2026

  1. Please fix aggregate_initialize_overload to make it use is_convertible_without_narrowing.
  2. Please add these test cases:

@saki7
Copy link
Member

saki7 commented Mar 12, 2026

I think is_assignable_without_narrowing should also be added here as a companion utility, not in X4. After that, I think it looks good to me.

// is_assignable_without_narrowing<Dest, Source>
//
// True when `Dest = Source` is valid AND does not involve a narrowing conversion.
// For non-arithmetic Dest types, narrowing is not checked — we trust that the
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For non-arithmetic Dest types, narrowing is not checked

Why? This doesn't make sense at all.

"—" is a very bad sign for vibe coded slop. Please, please double check both the description and code itself.

Do you really think "not is arithmetic" can be the constituent part for being "assignable without narrowing"?

Arithmeric types are just arithmeric types. There should be absolutely no direct relationship to the concept of "assignable", whatever the condition is.

Am I missing something?

I'm really disappointed to see this level of low quality code.

Copy link
Member Author

@yaito3014 yaito3014 Mar 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As noted in the clarification, is_assignable_without_narrowing itself was for detecting narrowing conversion, so it was just is_assignable for non-arithmetic types. The "mistake" was that the trait was used directly in X4 codebase, not the trait definition.
I admit that the clarification was missing, but before saying "vibe coded slop" or "low quality code", rethink about it.

@saki7
Copy link
Member

saki7 commented Mar 12, 2026

I just realized that even the implementation for is_convertible_without_narrowing diverges from the original implementation described in the paper. Please (1) add test that correctly asserts the current (wrong) implementation to false-positive value, and (2) Fix the definition.

This mistake was not caught on my first review because I trusted your code initially. It seems like I have to be extra careful since you posted some AI coded crap!

@yaito3014
Copy link
Member Author

yaito3014 commented Mar 13, 2026

add test that correctly asserts the current (wrong) implementation to false-positive value

The former implementation DID work except for void to void "conversion" BTW.
https://godbolt.org/z/cEcK3fW8j

The differences from original were:

  • requires parameter vs declval
  • existance of same_as<To[1]>

The first is just styling difference.
The second is a too verbose check, since we are passing only one initializer to To[].

The original reference implementation fails on void to void case too, so implementing the exact same trait is also wrong, yet the author already mentions about it.

Comment on lines 277 to +279
template<class T>
auto operator()(Ti, T&&) -> aggregate_initialize_tag<I, Ti>
requires requires(T&& t) { { TiA{std::forward<T>(t)} }; } // emulate `Ti x[] = {std::forward<T>(t)};`
requires is_convertible_without_narrowing_v<T, Ti>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the first parameter Ti can be omitted, as it existed for checking is_convertible by passing-by-value

Copy link
Member Author

@yaito3014 yaito3014 Mar 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, the Ti parameter cannot be omitted, since we should consider overload resolution for Ti including implicit conversion sequence's priority.

For example, constructing rvariant<int, long> from int should be resolved to index() == 0 though both int and long are equally convertible from int without narrowing. This is because identity conversion should occur prior to integral promotion in standard conversion.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[P0870R6] A proposal for a type trait to detect narrowing conversions

2 participants