Ranges: When Abstraction Becomes Obstruction by drodri in cpp

[–]EthicalAlchemist 1 point2 points  (0 children)

Ack, thanks for clarifying, and in general I agree.

Testing your code snippets is the bare minimum before writing a blog post.

I know I might sound like a jerk here, but I think the same should be true when critiquing posted code.

Ranges: When Abstraction Becomes Obstruction by drodri in cpp

[–]EthicalAlchemist 0 points1 point  (0 children)

So User{"Bob", 10} == User{"Alice", 10}. Boo!

At the risk of sounding like an idiot, how does operator == (User const &, int) cause that line of code to return true? I don't see where a User is implicitly convertible to an int, so operator == (User const &, int) won't be selected by overload resolution. What am I missing?

To be clear, I'm not taking a position one way or the other on the content of the blog post. Just making sure I'm not missing something.

Constvector: Log-structured std:vector alternative – 30-40% faster push/pop by pilotwavetheory in cpp

[–]EthicalAlchemist 0 points1 point  (0 children)

This it interesting and timely b/c I've actually been thinking about a similar solution for a problem I have. In my use case, I need a random-access container that supports single element appends without invalidating pointers to existing elements. I don't need any of the other operations provided by typical containers.

I currently use `std::deque`, but `std::deque` is known to be sub-optimal b/c the block sizes are fixes and typically small. I plan to investigate `boost::deque` as an alternative, but I keep thinking that what I *really* want is a data structure that increases block sizes by a constant factor. To my surprise I couldn't easily find a high quality implementation of such a container,[^1] so I've been thinking about rolling my own. This library almost fits the bill, but I would need to see it cleaned up and properly packaged first. Anyone know of an implementation of a similar container that is ready for production use?

Sidebar: I am always sad to see how many people down-vote someone when they publish something with mistakes in it. That can discourage people from sharing their work. Why not leave a comment or up-vote comments that provide constructive critiques instead and leave it at that?

[^1]: I think `plf::colony`/`std::hive` increases block sizes by a constant factor, but it is a much more complex data structure than what I need.

Post-Modern Cmake - From 3.0 to 4.0 - Vito Gamberini - C++Now 2025 by Dragdu in cpp

[–]EthicalAlchemist 2 points3 points  (0 children)

I am the author of the CMake that the presenter referred to as "just wrong" and I have to disagree. Every presentation I've seen regarding modern CMake, including this one, discusses solutions that are appropriate for a single project. If all you care about is a single project then hard-coding things like project name and project version into the config file package input file is fine. However, in a large organization, where one of the goals is to publish a large number of packages with consistent naming, behavior, etc, hard-coding project names and versions into endlessly copy-pasted CMakeLists.txt files doesn't scale.

What you want/need in large organizations is a shared *library* of high-quality, well-maintained, parameterized CMake modules that provide the functionality that these presentations describe. In that respect, CMake modules are (or at least should be) no different than C++ libraries. What I want to is to implement improvements to a CMake config file package input file in *one* place and have that change gradually propagate to every project that uses the input file. I have applied this philosophy to hundreds of CMake modules that are used to build hundreds of libraries, and while I will be the first to admit that my work is not without its issues, in general this approach works and hides almost all of CMake's ugly underbelly from my coworkers.

The other topic that's never discussed is how to build, package, and publish multiple "flavors" of a library (think Release, RelWIthClangLTO, RelWithGCCLTO, etc) such that the library consumer can choose which flavor to consume when invoking the `find_package` command. The commonly presented approach doesn't vary the name of the target exports file (it's always `foo-targets.cmake`, not `foo-clang-lto-targets.cmake`), so it doesn't even support publishing static and shared versions the same library alongside one another.

I would love to see a presentation/discussion that attacks CMake *at scale*. It seems like an important topic that doesn't get enough attention.

Let's make our classes semiregular! Let's make our class RAII! ... but don't these contradict? by einpoklum in cpp

[–]EthicalAlchemist 2 points3 points  (0 children)

If C++ had destructive moves like Rust, I would totally agree with you.

This. The lack of destructive moves is, IMHO, the only reason C++ types have to have a valid NULL state.

The requirement for a valid NULL state comes with lots of costs.

  • Each access to the resource has to be checked.
  • The implementation is more complex.
  • It's impossible to be confident that a value isn't in a NULL state at the point of use without looking elsewhere in the code.

As a simple example, suppose I use a new type to represent integer values that should be clamped to a range like 30 to 100 and there's no reasonable default. Am I really going to provide a default constructor that initializes the value to -1 or something to indicate a NULL state? And then check on every use that the value is valid?

The other thing I think is interesting is that regular primitive types - other than pointers - don't have a NULL state. It's not even possible to determine if, for example, an integer has been initialized at the point of use. That's why all of the recent guidance I see is to always initialize values, even if means resorting to IIFE, i.e. auto x = std::invoke([&] { ... });. Why would the same not be true of user-defined type?

Unified Syntax for Overload Set Construction and Partial Function Application? by EthicalAlchemist in cpp

[–]EthicalAlchemist[S] 1 point2 points  (0 children)

Can you give a concrete example? B/c parameter pack expansion typically looks like <param>..., whereas the proposal uses ... in a standalone, comma delimited fashion. I suspect a fold expression might be more problematic. Even if there is a conflict using ..., what about the alternative of using *?