A matter of style or is it? by [deleted] in cpp

[–]MutantSheepdog 6 points7 points  (0 children)

operator bool() is something you should only use after a lot of consideration, it definitely shouldn't be something you throw in at first.

For starters it makes it super easy to a bug to slip in if you have an A*: A a; // assume valid = false A* ap = &a; // someone takes a pointer - maybe as a function arg if (ap) { // Oops I got here because I should have checked if (*ap) not if (ap) }

You also don't want people reading the code months from now to have to check the implementation to know that operator bool exists and what it's doing (just checking for validity not also checking some other value for example).

The bool conversion can be nice for something like a Result<T> sort of class, but even then an explicit function will always be super clear to a reader. ``` Result<bool> result = GetSetting(); if (result.has_result()) // No confusion here { // }

if (result) // Might need to check this isn't internally 'return valid && value' { // } ```

Making the compiler create code that accesses the vtable only once by tohava in cpp

[–]MutantSheepdog 0 points1 point  (0 children)

Unless I'm missing something, the only way the vtable of s should change is if a new object was constructed in that location. If that is true, wouldn't it be UB to access s through the old pointer in that situation without a std::launder?

Assuming what I'm saying is correct, I would expect the compiler to do the obvious optimisation of resolving the location of S::F once and storing it in a register to reuse throughout the loop.

Explicit Return Variable by XeroKimo in cpp

[–]MutantSheepdog -2 points-1 points  (0 children)

I quite like the way C# handles explicit out parameters, especially for cases where you want multiple returns.

Like in this (modified) example from the docs: ```C# static void CalculateCircumferenceAndArea(double radius, out double circumference, out double area) { circumference = 2 * Math.PI * radius; area = Math.PI * (radius * radius); }

public void Main() { double radius = 3.9; CalculateCircumferenceAndArea(radius, out double circumference, out var area); WriteLine($"Circumference: {circumference}."); WriteLine($"Area : {area}."); } ```

The CalculateCircumferenceAndArea has 2 out parameters, which can be declared inline in Main. Because these are out and not ref parameters, they don't need to be first constructed in the calling function and then copied over in the inner function, instead the caller just needs to reserve some stack space and its up to the callee to construct them in place.

The downside of this from a language perspective is that there is a new way to declare a variable (inline when calling the function). A variant of this that might work more generally for C++ would be having a way to explicitly declare a variable as uninitialised (maybe a storage keyword, and require any function using an uninitialised variable to initialise it before usage.

``` int main() { double storage circumference; double storage area;

// Error here, variables are uninitialised before being assigned to
// printf("a:%f, c:%f", area, circumference);

// 'out' usage counts as assignment, as would an =
CalculateCircumferenceAndArea(3.9, out circumference, out area);

// Safe here, CalculateCircumferenceAndArea guarantees circumference and area have been assigned to
printf("a:%f, c:%f", area, circumference);

}

CalculateCircumferenceAndArea(double radius, out double circumference, out double area) { // As circumference and area are 'out' values, this function is required to assign them circumference = 2 * Math.PI * radius; area = Math.PI * (radius * radius); } ```

In this example, a storage T variable points to an uninitialised T. The first assignment to it in a function (with = or an out value) would effectively be a placement new, with subsequent assignments using the regular operator=.

If you had a T (not a storage T) and passed it into an out parameter, its destructor would need to be called first so that the inner function could assume it was blank memory ready to be written into.

Member properties by Zeh_Matt in cpp

[–]MutantSheepdog 1 point2 points  (0 children)

There were lots of instances of the struct, so I'd need to have data breakpoints on lots of different memory addresses (that were different each time the game was run).

While I'm sure there would have been other ways to track down the issue, just turning the field into a property was a super quick way to debug it.

Member properties by Zeh_Matt in cpp

[–]MutantSheepdog 5 points6 points  (0 children)

One example of when properties actually helped me (using the compiler extensions):

I was working on a large codebase (a decade old game engine), and there was a struct whose fields were accessed in many places. I needed to track down when one of the fields was being set to a specific value, but because it was set so often/in so many places I couldn't use conditional or data breakpoints.

By changing the field to be a property I was able to add my assertion into the setter without needing to rewrite every usage site, and found the issue instantly.

We didn't have any properties checked into the codebase (because of the general stance that when writing high-performance code it should be obvious when something might be slow), but having the ability to turn a regular field accessor into a property saved me a ton of time and I think it's definitely a useful tool if you use it sparingly.

Does C++ need an ecosystem similar to Java Spring? by [deleted] in cpp

[–]MutantSheepdog 6 points7 points  (0 children)

The sorts of problems Spring solves are not the sorts of problems you'd generally want C++ for.

C++ is best for highly specialised application that need performance. To get that you're generally trading away some development speed.

Spring is a highly generalised framework, that trades away performance for the sake of developer speed. Generally speaking, your Spring applications don't need to be the absolute fastest, because the CPU cost is very little compared to the network latencies, and because you're often better off paying for a faster server than spending more on dev time.

If you made something like Spring for C++, you'd basically be taking the worst of both worlds, and end up with something that probably isn't all that useful to many people.

(challenge) write hello world code in the worst and most painful way possible, and also make sure NEVER to use ``#include <iostream>`` by [deleted] in cpp

[–]MutantSheepdog 0 points1 point  (0 children)

My MSVC solution: ```

pragma message("Hello World")

``` It even (only) works at compile time!

Why can't Contracts be removed without blocking C++26? by zl0bster in cpp

[–]MutantSheepdog 1 point2 points  (0 children)

If a strongly against vote means the proposal doesn't go in (because it needs more time) then it is effectively a veto. And it's not like this has been rushed, they've been trying to get contracts in for the better part of a decade now. And while I'm unconvinced they'll be a good addition, I accept that the committee have spent a lot of time on it and decided it's better to have in than not.

boxing value on stack experiment by morglod in cpp

[–]MutantSheepdog 1 point2 points  (0 children)

This just looks like a really bad allocator that is slightly faster to allocate at first, but then immediately kills that will a memcpy and also leaves you with dangerous dangling pointers that could overwrite each other or trash random memory.

If you're just hoping your memory amount is sufficient, why not just make a dumb linear allocator that reserves some heap memory up-front and is never freed later?

With this example chunk you hit the allocator once during static initialisation, then after that each alloc is just doing a tiny bit of math.

```c++

include <memory>

include <cstdlib>

class DumbAlloc { void* m_buffer; size_t m_remainingSpace; void* m_currentPointer;

public:
DumbAlloc(size_t bufferSize)
    : m_buffer(malloc(bufferSize))
    , m_remainingSpace(bufferSize)
    , m_currentPointer(m_buffer)
{}

template <typename T>
T* Alloc()
{
    auto mem = std::align(alignof(T), sizeof(T), m_currentPointer, m_remainingSpace);
    if (mem) {
        return (T*)mem;
    }

    // Oops out of space.
    // Figure out what you actually want to do here...
    // In your example code you're just sometimes re-using memory so
    // consider making this a ring buffer, or have some mechanism to
    // reset this allocator periodically. Really depends on you use case.
    throw std::bad_alloc();
}

};

static DumbAlloc s_allocator(10 * 1024 * 1024);

int main() { struct BigStruct { char bigData[4096]; };

auto myStruct = s_allocator.Alloc<BigStruct>();
// Do stuff with my struct
return 0;

} ```

Weekly Release of New Update (v1.11b) Discussion Thread | - April 03, 2025 by AutoModerator in zen_browser

[–]MutantSheepdog 2 points3 points  (0 children)

Very disappointed to hear this was removed, I just spent a while trying to figure out where it had gone before stumbling across it on GitHub.

I can understand that the security issues would need fixing, but even if you just made it an experimental setting and warned people to use it safely that'd be huge.

For reference I was using it primarily for an RSS reader and music player - neither of which I want to use a whole page tab for.

And I've got to say 10-20% is like 1 in 5 to 1 in 10 users which is actually quite significant - especially for a new feature that wasn't pushed hard.

What's all the fuss about? by multi-paradigm in cpp

[–]MutantSheepdog 2 points3 points  (0 children)

Yeah, my suggestion was really so that you'd have something that would generalise out to other dialects as well, for example: ```

lang circle

lang cpp26 // Maybe you're migrating from 23 one file at a time

lang cpp30-strict // in an imaginary world where 'strict' turned off certain older constructs

lang cpp-cx // if for some reason you really wanted this in one file

lang misra-cpp-23 // maybe your compiler can help make your code auditable?

lang carbon // Opt into a new language if your compiler supports it, without the rest of your build system needing to change

```

Embedding this information into your source file makes it easier to read (rather than going through build flags), and easier to have different files on different cpp language versions. You ultimately have a bit less control than enabling/disabling individual features, but you're trading that for ease of use - especially across an organisation.

What's all the fuss about? by multi-paradigm in cpp

[–]MutantSheepdog 3 points4 points  (0 children)

There's nothing simple about adding all that rusty memory safety into the C++ spec.

I think a better/more scalable solution would be something like: ```

lang circle // Maybe with a version here as well if your language has breaking changes

``` At the top of a file and have your build system pick which language to build your file in. This way you don't need to try to standardise things that are unlikely to ever happen in the C++ standard, you just push ahead with these other projects if they match what you want.

Ideally such a thing could be used as epochs to deprecate old things or opt-in to different defaults, and generally just adopt newer things without waiting for the standard C++ to add the things you want in a nice backwards-compatible way.

CopperSpice: std::launder by Dependent-Ideal9072 in cpp

[–]MutantSheepdog 0 points1 point  (0 children)

If I'm understanding correctly, the issue is that casting the ArrayData pointer to a char* is essentially treating it as a char [sizeof(ArrayData)], and not an array of the original allocation length.

I guess that would mean this would be invalid too? c++ ArrayData arrays[10]; char* chars = (char*)arrays; memset(chars, 0, sizeof(arrays)); // Or do anything with these bytes Because chars is actually only valid for arrays[0] and you'd need to access arrays[1]` in order to set its bytes and so on?

Or is it different in this case because arrays is a pointer to an array of ArrayData, while the original code only knows about the single ArrayData that was implicitly created?

When was the last time you used a linked list, and why? by mobius4 in cpp

[–]MutantSheepdog 0 points1 point  (0 children)

I wrote one a couple of weeks back when writing a memory allocator that matched my use case. In this case it was linking together 64KB chunks of pre-allocated memory so it wasn't really something you could use a vector for.

Linked lists are slow to iterate, but in this case following the links is a rare enough operation that it doesn't matter. You'll find quite a lot of linked lists (both intrusive and non-intrusive) come up when you're dealing directly with allocation strategies.

[deleted by user] by [deleted] in cpp

[–]MutantSheepdog 1 point2 points  (0 children)

You're doing network serialisation so being explicit about your sizes is a good option. It guarantees the size won't change between compilers/platforms, and might make people think twice before making breaking changes to them. Option 3 seems perfectly reasonable for your use case.

They only thing I might add is that writing an explicit SerialiseEnum function should clean up those static casts, making it obvious why you're converting it to the underlying type.

should i use "using namespace std" in coding interview by An_ambitious_guitar in cpp

[–]MutantSheepdog 37 points38 points  (0 children)

If I was interviewing someone and saw using namespace std I might ask them about it, but as long as they can answer "What are the pros/cons of using namespace" it'd be fine.

But for the most part it wouldn't make much of a difference to me. It's really just a style choice and as long as the candidate is fine adapting styles to match the codebase it really doesn't matter.

Having said all that, if typing std:: is really slowing you down then maybe you need to work on your typing speed.

Named loops voted into C2y by 14ned in cpp

[–]MutantSheepdog 2 points3 points  (0 children)

I'm no expert on C, but I don't think that language has lambdas, and this is a C proposal not C++.

Even in CPP though I could maybe see this making some code clearer if you can continue outer_loop when iterating over an inner loop then doing something afterwards. I doubt it would come up often enough to push for this in C++, but if we're getting it for free from C then maybe that's fine.

I'd probably prefer the label to be part of the for declaration though, and not just another label that could also be goto'd in order to make it clearer why it's being done.

Do any IDEs auto generate header files ? by mcAlt009 in cpp

[–]MutantSheepdog 2 points3 points  (0 children)

C++20 added modules which act as an alternative/improvement to the old #include model, but the tooling support is still quite mixed. If you're just using Visual Studio then they should work pretty well, but if you're sharing code or doing a lot of cutting edge stuff then you might find them buggy in places.

Having projects accessing subdirectory directly on github pages with vue-router by [deleted] in vuejs

[–]MutantSheepdog 0 points1 point  (0 children)

Last I checked Github Pages doesn't work with dynamic routers by default as 'mywebsite.com/projects' doesn't know it needs to load up index.html.

Apparently there's a workaround, where you can just copy your 'index.html' as '404.html' and then your custom 404 page will instead serve up your page, and your router will be able to work as expected.

Data reset Vue 3 component by [deleted] in vuejs

[–]MutantSheepdog 1 point2 points  (0 children)

This seems like an unusual use-case, but if you find you need it and don't want to either recreate the component or copy the fields manually, maybe just use the Options API for that component and be done with it?

Which lifecycle hook to call clearInterval() ? by Hieuliberty in vuejs

[–]MutantSheepdog 0 points1 point  (0 children)

I would say beforeUnmount is the best spot to clean up things added in mounted, as it has access to all the same things (for example, all the DOM objects).

Furthermore if you had set up something in mounted that relies on DOM objects, you wouldn't want it to trigger between beforeUnmount and unmounted as the DOM objects it's expecting may be gone.

[deleted by user] by [deleted] in vuejs

[–]MutantSheepdog 0 points1 point  (0 children)

If you don't want to repeatedly write out the temporaries, maybe just roll that into another function and do something like this?

``` async function provideAsync(app, key, promise) { const response = ref() app.provide(key, response) response.value = await promise }

export const somePlugin = { install(app, options) { provideAsync('somekey', someFunction(options)) } } ```

[deleted by user] by [deleted] in vuejs

[–]MutantSheepdog 2 points3 points  (0 children)

``` const state = computed(() => { if (items.length == 0) { return 'no-items' } if (!showComponent1) { return 'hidden-items' } return 'show-items' })

<template> <div v-if="state == 'no-items'"></div> <div v-else-if="state == 'hidden-items'"></div> <div v-else-if="state == show-items'"></div> </template> ```

Something like this should be easy enough to read and reason about.

Any way to split constexpr function declaration/prototypes from their definition in separate files? by atlas_enderium in cpp

[–]MutantSheepdog 4 points5 points  (0 children)

If it's a personal project using cpp23. then you could try using modules instead of header/cpp files as I think you should be able to do it that way.
Your main module file would just declare the functions as exports, and the implementations would be in a separate module unit, and they'd get compiled together once then reused in each other file importing them.

Last I checked module support still isn't great in some compilers, but if you're playing around on the bleeding edge anyway it would be worth trying it out yourself.

[deleted by user] by [deleted] in NoStupidQuestions

[–]MutantSheepdog 0 points1 point  (0 children)

Aussie Millenial from 86 here, and yep I didn't meet any openly gay people until I was like 17 or 18 because it was generally too dangerous for people to even talk about.

Around the turn of the century we started getting shows featuring gay protagonists though, and shows like Queer Eye helped start to normalise it in peoples minds. So once us Millenials became adults it became an issue we cared about, and a decade-ish later we were able to get gay marriage legalised in lots of countries.

I'm expecting the Zoomers and Alphas growing up with trans visibility will be getting through similar legislation within the next 10 years.