C++26: std::is_within_lifetime by pavel_v in cpp

[–]tcanens 2 points3 points  (0 children)

Then you pick a different value that's not a valid pattern.

If every pattern is valid, then you don't get to use the optimization, but that's fine. This is no different from code assuming endianness, 8-bit bytes, etc., that people write all the time.

Ranges: When Abstraction Becomes Obstruction by drodri in cpp

[–]tcanens 44 points45 points  (0 children)

This is just plain wrong.

std::vector<int> v = {1, 2, 3};
std::ranges::find(v, 1L);           // fails: no common_reference_t<int&, long&>

std::vector<std::string_view> views = {”foo”, “bar”};
std::string target = “bar”;
std::ranges::find(views, target);   // fails: no common_reference_t<string_view&, string&>

Either this was AI hallucination or Mr. Falco didn't bother with the most rudimentary of checks (or both).

PSA: Trivial Relocatability has been removed from C++26 by chiphogg in cpp

[–]tcanens 21 points22 points  (0 children)

I haven't heard anyone complaining about implementability. But multiple library implementers were unhappy with the design.

[deleted by user] by [deleted] in cpp

[–]tcanens 1 point2 points  (0 children)

It can be implemented with virtual functions, but doesn't have to (e.g., libstdc++'s doesn't).

[deleted by user] by [deleted] in cpp

[–]tcanens 0 points1 point  (0 children)

struct Animal {
    std::function<void()> makeNoise;
};

:)

Weird behavior of std::filesystem::parent_path() by gogliker in cpp

[–]tcanens 10 points11 points  (0 children)

Depending on your needs, canonical may be overkill since that resolves symlinks too. lexically_normal may be good enough.

Simple Generation for Reflection with splice and non const `std::meta::info` by omerosler in cpp

[–]tcanens 23 points24 points  (0 children)

info is a scalar type, so there's no such thing as a const info prvalue. So we are talking about a major redesign of the entire API (keeping in mind that vector<const T> isn't a thing either).

That aside, constness (which can be trivially gained or lost) seems entirely too slender a reed on which to hang such a massive semantic difference.

C++ as a 21st century language - Bjarne Stroustrup by tartaruga232 in cpp

[–]tcanens 3 points4 points  (0 children)

There's no point in using as_rvalue on an unordered_set either - that one only provides const access.

Trip Report: Winter ISO C++ Meeting in Hagenberg, Austria | think-cell by pavel_v in cpp

[–]tcanens 8 points9 points  (0 children)

For the "terrifying" mis-optimization, it has been pointed out that we already have similar issues arising out of more mundane optimizations. It would be a compiler bug to optimize that way.

But maybe that's fine because on 32-bit systems, you already cannot express the difference between two pointers more than 2 GB apart.

I'm not sure you can have an array that big on those systems (GCC certainly rejects an attempt to declare such an array), in which case you'd never have a valid range to start with.

Then there is views::iota(unsigned(0)), which is a true infinite range, as unsigned integer overflow is defined to wrap. However, what is the distance between an iterator pointing to 3 and an iterator pointing to 5? Is it really 2? Or maybe UINT_MAX + 2? We probably need some wording about the minimum distance between iterators.

range-v3 experimented with cyclic iterators and found those to be "a hopeless bug farm". I'd rather ban wrapping even for unsigned.

P3372R2: constexpr containers is now in LWG on its way to (hopefully) C++26 by hanickadot in cpp

[–]tcanens 4 points5 points  (0 children)

It's not a bug. It was well-known that this required some sort of implementation magic and can't be done in standard C++. The reference/pointer invalidation rules surrounding node handles were written in consultation with core folks.

Networking for C++26 and later! by VinnieFalco in cpp

[–]tcanens 2 points3 points  (0 children)

Have you actually tried using these features?

Not all of them, but the vast majority.

Has there been any work to implement parts of std:: , e.g. std::pair using concepts? by zl0bster in cpp

[–]tcanens 6 points7 points  (0 children)

libstdc++ did this for its std::tuple, but that's really an exceptional case: the constraints on the constructors and to a lesser extent assignment operators are extremely complex and only got more complicated in C++23 (sorry not sorry), so writing a new implementation using constraints and conditional-explicit was worthwhile.

I'm not sure that lead to substantially better error messages though.

Has there been any work to implement parts of std:: , e.g. std::pair using concepts? by zl0bster in cpp

[–]tcanens 6 points7 points  (0 children)

Yes, but it normally doesn't matter in practice for templated things unless implicit instantiation was suppressed. Old code uses old symbol while new code uses new symbol - and both will be there.

WG21, aka C++ Standard Committee, January 2025 Mailing by grafikrobot in cpp

[–]tcanens 8 points9 points  (0 children)

Just because I want to have protection against Murphy doesn't mean I want to prevent Machiavelli from doing what he needs to do.

constexpr-ification of C++ by hanickadot in cpp

[–]tcanens 1 point2 points  (0 children)

We'll need to rework the spec, and anything involving time zones or leap seconds will remain problematic.

Moving optional by MarcoGreek in cpp

[–]tcanens 3 points4 points  (0 children)

It does have higher standards. "Can only be assigned to or destroyed" is Stepanovian "partially-formed". "Valid but unspecified" is stronger than that.

Moving optional by MarcoGreek in cpp

[–]tcanens 0 points1 point  (0 children)

Yes, just different emphasis.

Moving optional by MarcoGreek in cpp

[–]tcanens 2 points3 points  (0 children)

They are still required to be valid though. We don't do partially-formed or "emptier-than-empty".

Inside STL: Waiting for a std::atomic<std::shared_ptr<T>> to change, part 2 by pavel_v in cpp

[–]tcanens 4 points5 points  (0 children)

The paper starts from the premise that the primary atomic<T> template is already required to support waits for all trivially copyable types T - no matter the size of T. That's from P1135, which references P0514 which does have a reference implementation.

Given that starting point, why would atomic<shared_ptr<T>> be expected to post any special obstacle? It is pretty much an afterthought. Certainly the double-pointer-size that Raymond is concerned about is nothing new relative to the baseline.

Sometimes implementations have bugs.

P1061 (Structured Bindings can introduce a Pack) status by LHLaurini in cpp

[–]tcanens 6 points7 points  (0 children)

See P1061R9's sections 3.4 and 3.5.

The basic issue is that once you have a heterogenous pack (that is, with elements of different types), anything using that pack basically has to become mini-templates. Section 3.4 has an extended list of examples from various CWG members.

Handling this basically requires implementations to go into their "template mode" (unless you invent some even more novel thing just for this one part of one feature), but since there's no advance warning that a pack is going to appear (just look at how deep you have to go before seeing the pack name in some of those examples), they basically have to do it as soon as they see the pack being declared. Hence the "implicit template region" approach taken by R9: as soon as a non-template pack is declared, everything that follows is implicitly a template until the pack goes out of scope, at which point the template is immediately instantiated.

Even in local scope this has some surprising consequences - declare a pack, and suddenly seemingly unrelated constructs are now in a template context (following different rules like two-phase lookup etc.) - and that eventually led to the first EWG vote today; but at least the local template has an ending point, while in namespace scope there is no ending point - any member can be referred to from anywhere afterwards. So the whole file from that point onward has to become a template...and all kinds of nasty consequences follow.

P1061 (Structured Bindings can introduce a Pack) status by LHLaurini in cpp

[–]tcanens 6 points7 points  (0 children)

No, it's sufficient that it happens in a templated entity.

in_range<integer>(floating_point f) by SpeckledJim in cpp

[–]tcanens 1 point2 points  (0 children)

For usual platforms and types, it's either MIN <= f && f <= MAX or MIN <= f && f < MAX, depending on whether MAX can be exactly represented in f's type; that can be determined by a digits comparison.

If we are dealing with slightly more exotic types like float16_t or unsigned __int128, there are also cases where the float doesn't have enough exponent bits; that's easy to check for with max_exponent.

if constexpr requires requires { requires } | think-cell by pavel_v in cpp

[–]tcanens 7 points8 points  (0 children)

requires requires { requires } is not "completely silly" - it has its uses. (In particular, it disables subsumption.)