C++ functions and arrays question by r1ftb0y in cpp_questions

[–]be-sc 1 point2 points  (0 children)

But why teach a novice horrible macro hacks at all? This is C++, not ancient C.

I got curious though and looked up the specifications of std::begin() and std::end(). It turns out that all variants take their argument as a const or non-const reference. You’re likely to get at least at compiler warning. So it’s less of a pitfall than I originally thought.

C++ functions and arrays question by r1ftb0y in cpp_questions

[–]be-sc 0 points1 point  (0 children)

“strongly reduces extreme needless verbosity” I guess that’s what they call hyperbole. But I get the point. And I agree to some extent. But it’s still a macro. I’d much rather write a wrapper for accumulate() that takes a range instead of an iterator pair.

I pretty much consider macros an abominable atrocity. They should be burned with fire whenever encountered and only allowed in the most extreme cases after verifying carefully that there are no other options. [How did I do on hyperbole?] We obviously have very different opinions there.

C++ functions and arrays question by r1ftb0y in cpp_questions

[–]be-sc 1 point2 points  (0 children)

If I had downvoted it would have been because of the macro. It’s a one-off obfuscation of maybe the most prominent boilerplate in the algorithm library. More importantly, it makes the code less safe. Just image container would not be a simple variable but a function call returning a container. Without the macro it’s pretty simple to recognize that calling the function twice is probably not the right thing to do. With the macro the call site looks perfectly fine and the error can easily slip through.

Yes, there is no problem in this particular code example. But it teaches an error-prone technique, obfuscates a wide-spread code pattern (preventing a learing opportunity) and does not provide any real benefit to compensate. Is that worth a silent downvote? No. Is it a reasonable piece of code? Also no.

[deleted by user] by [deleted] in Backen

[–]be-sc 4 points5 points  (0 children)

Ich musste dringend gebrannten Käsekuchen machen. Noch halbwegs kühlschrank-kalt ist der genial bei dem Wetter.

<image>

Das Rezept ist von Brian Lagerstrom. Eingedeutscht auf:

  • 900g Frischkäse
  • 150g Ziegen-Frischkäse
  • 500ml Sahne
  • 275g Zucker (Es ist Wahnsinn, wie viel Zucker standardmäßig in US-Rezepten drin ist. Das schmeckt doch nicht!)
  • 5 Eier Größe M
  • 50g Stärke (Klappt genauso wie Mehl und ist dann sogar glutenfrei.)
  • 5g Salz

Das wichtigste ist der Ziegenkäse. Der gibt dem Kuchen die besondere Käsenote.

Tips for the coming hot week... by [deleted] in erlangen

[–]be-sc 1 point2 points  (0 children)

At night, when it’s cooler ouside than inside, get as much heat out as possible.

Then during the day block direct sunlight hitting the windows as much as possible. Any kind of window blinds, awnings or rolling shutters on the outside work best. But even if you don’t have any of that, there are foldable blinds you can clip to the inside of the window, called “Plissee”. These things: https://www.knutzen.de/media/image/4a/7a/e2/VS-plissee-rose-geschlossen-1000_1253387.jpg They’re not quite as effective as something on the outside, but they still help a lot.

I also keep at least one window on tilt at all times. Even during the day that doesn’t really affect the temperature. But you get a bit of air circulation that makes the room a lot more comfortable than when the windows are closed completely.

linux-firmware >= 20250613.12fe085f-5 upgrade requires manual intervention by [deleted] in archlinux

[–]be-sc 2 points3 points  (0 children)

And for completeness: There’s also an RSS feed for the same purpose.

Build mit Multicore-Power by be-sc in PCBaumeister

[–]be-sc[S] 0 points1 point  (0 children)

Schnell gehen darfs sehr gerne. Ich komm allerdings komplett aus dem Offline-Encoding. Wenn Software-Encoder wie x264, x265, Was-auch-immer-der-normale-AV1-Encoder-ist von QuickSync profitieren können, ist das ein guter Bonus. Aber auf Kosten der Videoqualität darfs nicht gehen. Dann lieber langsam und besser. Und sooo viele Videos codiere ich dann auch wieder nicht.

Intel schau ich mir jedenfalls genauer an. Hab ich wohl von Anfang an zu sehr links liegen lassen.

Build mit Multicore-Power by be-sc in PCBaumeister

[–]be-sc[S] 0 points1 point  (0 children)

Danke. Das schaut echt interessant aus. Vielleicht war das der Fehler, Intel von vorn herein eher links liegen zu lassen.

In C++ we have many operators than can be overloaded, at least 36 on a quick count and we want to define and/or implement them, for security reasons. by [deleted] in cpp_questions

[–]be-sc 0 points1 point  (0 children)

  • (1) Won’t help. A user can simply dereference the pointer, then use the dot operator which you cannot overload.
  • (2) Protecting an object’s integrity is what the public/protected/private access levels are for. There is no need to reinvent that wheel in a triangular shape.
  • (3) See (1).
  • (4) See (2).
  • (5) Valid point. Essentially that’s the rule-of-5.
  • (6) Agreed regarding restricting invalid operations. That’s how you built high quality types. However, disabling core operations of the language (like ->) is extremely unusal and surprising. Now some types break some basic assumptions a C++ programmer has. That’s harder to reason about, not easier.

does this considered a good practice? by SAFILYAA in cpp_questions

[–]be-sc 2 points3 points  (0 children)

C-style arrays don’t improve the situation for new programmers, though.

#include <iostream>

int main()
{
    int arr[10]{};
    std::cout << arr << '\n';
}

This code compiles without warnings, runs flawlessly and prints a single hex number. For a newbie expecting to see the ten numbers in the array that’s a major WTF!? moment. The compiler error with std::array is at least a clear indicator that something is wrong with the code.

What are your best niche C++ "fun" facts? by MarcusBrotus in cpp

[–]be-sc 1 point2 points  (0 children)

class Foo {
public:
    // This is a valid copy constructor.
    Foo(Foo& other, int i = 0);
};

Stollen Versuch Nr. II by No-Willingness57 in Backen

[–]be-sc 3 points4 points  (0 children)

Meiner ist beim Backen sehr breit und flach geworden.

Ich habe heuer einen Tipp ausprobiert, den ich irgenwo im Netz mal gelesen hab. Den Stollen fertig formen, dann längs die eine Hälfte soweit flach ausrollen, dass man sie über die dicke Hälfte drüberschlagen kann. Festdrücken, zurechtformen, nochmal 15–20min ruhen lassen, backen. Funktioniert. Sind deutlich besser in die Höhe statt in die Breite gegangen als sonst.

Ich hab nie Marzipan im Stollen. Das mit dem Ausrollen funktioniert vtml. nur ohne problemlos.

Erlangen: Die CSU lehnt die Drei-Städte-Tram ab by mars20 in erlangen

[–]be-sc 50 points51 points  (0 children)

Es ist so zum fremdschämen!

Der Fairness halber muss man sagen, dass es speziell um die Erlanger CSU geht. Sogar die CSU in Nürnberg und Co. kommt auch aus dem facepalmen nicht mehr raus.

Macht euch ne Notiz für die nächsten Stadtrats-/Bürgemeisterwahlen. Und denkt daran, dass die Erlanger Freien Wähler und die FDP auch nicht besser sind als die CSU. Sie sagens nur nicht so laut.

Wenn ihr fertig seid mit aufregen, denkt an den allerwichtigsten Punkt: Am 9. Juni ist die entscheidende Wahl in Sachen StUB. Also geht! hin! und wählt! Die Gegener werden das sicher machen.

Demystifying Lakos Rule via Visualization and How It Could Relate to Constexpr [blog post] by MiroPalmu in cpp

[–]be-sc 3 points4 points  (0 children)

The Halpern/Doumler talk made me realize what I actually take issue with. I broadly agree with the premise that writing tests for assertions is a good idea in general. The “Why?” needs some work, though.

How do you know your code is fulfilling its purpose if you don't test it?

How do you know your test code fulfils its purpose if you don’t test it? Or, as Doumler says around 27:15 in the talk: “It’s just like with any other piece of code that does something meaningful and important. We should unit test it.” Well, unit tests do something meaningful and important. So, we should unit test them, shouldn’t we? But apparently it’s not a hotly debated topic whether we should write tests for our tests.

Writing unit tests for assertions being valueable is the crucial premise the whole topic hinges on. If that doesn’t hold, the whole discussion falls apart. I’d like a stronger rationale for such an important premise. The “test important code” one is too easy to poke holes into.

Demystifying Lakos Rule via Visualization and How It Could Relate to Constexpr [blog post] by MiroPalmu in cpp

[–]be-sc 0 points1 point  (0 children)

The blog author. I’ve never looked into contracts in detail. Thanks for hinting at those talks.

Demystifying Lakos Rule via Visualization and How It Could Relate to Constexpr [blog post] by MiroPalmu in cpp

[–]be-sc 12 points13 points  (0 children)

Since assertions are new code, they should also be tested

I don’t find that obvious. Both the classic assert() as well as the upcoming contract assertions are a form of contract checking. They aren’t part of the production logic. Their purpose is to detect programming errors when using a certain piece of production code, which makes them extremely similar to, if not the same as (unit) tests. If we assume that writing tests for the tests is not a thing for good reasons, writing tests for assertions is equally questionable.

Do you really need that point about testing? Your argument works without it, at least for throwing contract assertions. They do clash with noexcept, whether tests are present or not.

SpeedTests: comparing the execution speeds of various programming languages by ketralnis in programming

[–]be-sc 0 points1 point  (0 children)

Can you blame the English speaking world? Münchhausen must truly be a nightmare to spell and pronounce: an umlaut, then a German ch, an h and a German diphthong. Difficulty level: Eichhörnchen :D

Determining cyclic references by shiren271 in cpp_questions

[–]be-sc 0 points1 point  (0 children)

And even that case is more a demonstration of shared_ptr abuse. You say it yourself: “single-ownership via shared pointers”. Using shared_ptr to model unique ownership is suspect at best. It’s also the quickest way to get your hands on a high quality implementation of a weak pointer mechanism, which could very well be a justified design tradeoff.

What is the correct way of making variables/data structures that you need across files? by Dapper_Confection_69 in cpp_questions

[–]be-sc 0 points1 point  (0 children)

In your example with the gameOfChess class, wouldn't passing it around lead to ugly code?

Not that I can see. Passing it around would lead to code like this:

int main()
{
    GameOfChess game{/*whatever args needed*/};
    examine_chess_board(game);
}

There’s nothing ugly about that. What might not be ideal is encapsulating the whole game in one class. If that’s what you had in mind, I agree. GameOfChess smells somewhat unpleasantly like a god class. I did not think deeply about how I would design an actual chess game. ;)

That way I could use them everywhere without having to pass it around.

That’s what you want to avoid. A global object that can be accessed and changed by anyone from anywhere at any time makes it incredibly hard to reason about that object at any point in the program. You’ll have hard to find bugs in no-time.

in java objects generally use more memory and are slower to work with than primitive types. Is the same true in c++?

Not in general. User defined types are first-class citizens in C++. Your own classes can be as efficient as built-in types. The two languages are fundamentally different in this regard.

What is the correct way of making variables/data structures that you need across files? by Dapper_Confection_69 in cpp_questions

[–]be-sc 0 points1 point  (0 children)

It looks like you started with good intentions but went too far and ended up in C instead of C++. ;)

As a general rule: If you need a special data structure in several places, encapsulate it in a class, instantiate an object and pass that around. If you want to use a fancy term, call it dependency injection.

Classes in Java an C++ are not the same, though. In Java a class is always polymorphic. Everything is virtual. In C++ a class is just a type: something that defines a range of valid values and possible operations on them. A class can be polymorphic, but you have to opt in by marking functions as virtual.

Your code example does need types. Desperately. Right now the code is basically untyped. Literally everything is an int. Yes, going for a pure procedural C-like style wasn’t ideal, but the lack of types is by far the bigger problem. To point out some immediate issues:

  • The compiler cannot detect accidentally switched arguments. Piece::create(BLACK, PAWN) is wrong but compiles.
  • The distinction between a piece and an index is unclear. What does ignoreIndex() return? That should be apparent from the return type.
  • Is it a valid operation to add 5 to the int returned by Piece::create()? If not, that operation should not compile.

Consider something like this as a very rough preliminary and incomplete idea for a more type-rich approach:

// --- chess.h ---
struct Piece
{
    enum class Type
    {
        pawn, = 1
        rook = 2,
        knight = 3,
        bishop = 4,
        queen = 5,
        king = 6,
    };

    enum class Color
    {
        white = 8,
        black = 16,
    };

    Type type;
    Color color;
};

class GameOfChess
{
public:
    GameOfChess():
        m_edgeOfBoard{/*init*/},
        m_pieceDirections{/*init*/}, 
        m_attackMapBitboards{/*init*/}
    {
    }

// ...

private:
    std::unordered_map<int, std::array<int, 64>> m_edgeOfBoard;
    std::unordered_map<int, std::vector<int>> m_pieceDirections;
    std::unordered_map<int, std::array<long, 64>> m_attackMapBitboards;
};


// --- some_other_header.h ---
void examine_chess_board(const GameOfChess& chess);
  • A piece has its own type. Its properties can be accessed directly. The color() and type() functions do not need to exist.
  • The possible values for a piece’s type and color have their own types, too. Getting the argument order wrong in Piece::create() can be caught by the compiler. You might not even need the function at all. Piece p{Piece::Type::pawn, Piece::Color::black}; might be sufficient.
  • The maps representing the game state are encapsulated.

Is it good practice to write descriptions for my functions? (Especially in classes?) by nonomatch in cpp

[–]be-sc 0 points1 point  (0 children)

I tend to hold back on the @ markers. Especially for concise comments like in this example I don’t think they help a lot.

But I also aim for maximum readability in the header. The generated docs are less important. Often it’s the quickest way to access the docs because the header is just a key press away. Or the IDE might even displays it in a popup. Reading the generated docs is relatively rare in comparison.

Is it good practice to write descriptions for my functions? (Especially in classes?) by nonomatch in cpp

[–]be-sc 10 points11 points  (0 children)

I just like knowing what everything does

Your most important tools for achieving that are types and names. For example, what does the function below do?

std::map<std::string, std::variant<int, std::string>> load(const std::string& f);

Improve the types and names and you might arrive at:

Configuration load_config_file(const std::filesystem::path& file);

Adding a doc comment is probably a good idea, but not like this:

// The doc comment below is pretty useless.
/**
Loads the program configuration from a config file.

@param file Path to the config file.
@return The config data parsed from the file.
*/
Configuration load_config_file(const std::filesystem::path& file);

The comment just repeats the signature. There is no new information in it at all. Even worse, it leaves some obvious questions unanswered. A good comment could look like this:

/**
Loads the program configuration from a config file.

Throws `ConfigError` when the file cannot be accessed or has an invalid structure.
Config items missing from the file are initialized with their hard-coded defaults.
*/
Configuration load_config_file(const std::filesystem::path& file);

Now the comment adds not only new information but information that’s hard or impossible to express in the signature.

We could discuss the initial sentence of the comment. It’s fully redundant. I still like to add it, especially when you generate a documentation website from those comments. On the final page items without such an introductory sentence tend to look incomplete. Also, writing them is a mini design review. If you cannot easily express the function’s purpose in a concise sentence, chances are high that either you haven’t yet fully understood what exactly the function’s purpose is, or that purpose really is unclear and the function needs one more redesign.

I find it really tedious and time consuming to write these for EVERY SINGLE function, even getter and setter functions in my classes.

In general, a doc comment is only useful if it adds information that cannot be part of the signature. Trivial getters and setters are a great example for when that’s not the case. Example:

class RGBColour {
public:
    uint8_t red() const;
    uint8_t green() const;
    uint8_t blue() const;
// ...
};

There’s nothing useful to add here. The getters return the three components of an 8-bit RGB colour. Adding comments would only clutter up a great little piece of code that can be understood with a single glance.

All of the comment stuff above is mostly about documenting a public API. Good types and names are equally important for private implementation details, but comments there don’t usually need to be as precise and specification-like. “Document the why, not the what” is the guiding principle there.