C++ - Reddit
226 subscribers
48 photos
8 videos
24.6K links
Stay up-to-date with everything C++!
Content directly fetched from the subreddit just for you.

Join our group for discussions : @programminginc

Powered by : @r_channels
Download Telegram
source_location::file_name is a misleading name

I think this is not suitably emphasized in cppreference...

source_location::file_name() is basically __FILE__ instead of __FILE_NAME__ (clang/gcc), which can be absolute path by default... This means if used without care, it may inject absolute path into release build. (Due to its name and c++-ish style, I doubt it's more likely to be abused than __FILE__.)

https://godbolt.org/z/e149Tqv4Y

#include<sourcelocation>
#include<filesystem>
#include<stringview>
#include<cstdio>

int main() {
constexpr std::stringview filename = std::sourcelocation::current().filename();
staticassert(filename == FILE);
if (std::filesystem::path(filename).isabsolute()) {
puts(":(");
}
}

https://redd.it/1odzc93
@r_cpp
Why does this code behave like this?

```cpp

#include <cstdlib>
#include <cstdio>
int main()
{
int *a = (int *)malloc(sizeof(int));
*a = 42;

for (int i = 1; i < 10; i++) {
a[i] = i;
}
for (int i = 0; i < 10; i++) {
printf("%d\n", a[i]);
}
}
Ouput :
malloc(): corrupted top size
Aborted (core dumped)
```
this is understandable that we are getting error over here but when we add a printf() after *a = 42. we do not get this error why is that
```cpp

#include <cstdlib>
#include <cstdio>
int main()
{
int *a = (int *)malloc(sizeof(int));
*a = 42;
printf("%d\n", a[0]);

for (int i = 1; i < 10; i++) {
a[i] = i;
}
for (int i = 0; i < 10; i++) {
printf("%d\n", a[i]);
}
}
Ouput :
42
42
1
2
3
4
5
6
7
657975
668983
```
can anyone explain reasoning behind this behaviour

https://redd.it/1oi40qg
@r_cpp
C++ is my first programming language

I am learning C++ as a required course for an engineering degree I'm pursuing. I never thought computational thinking was something I was capable of doing, so coding never crossed my mind as something that could be fun.

I am still in the basics but we just went over string literals and my brain just made a huge connection that C++ coding is broken down into string, character, double, boolean and integer categories.

Up until that point I was struggling with trying to learn each concept as if it were a wholly unique set of rules like learning a new language's verbs, nouns, etc. I obviously still have so much farther to go with learning C++, and I know this connection seems like a cout << "well duh" << endl; moment for anyone who's been doing this for longer than a week, but to someone growing up so "right brained" I finally feel like the computational side of the world is something I can be a part of. If just a little bit.

#include <iostream>
#include <string>
using namespace std;

int main () {

string firstWord;
string secondWord;

firstWord = "Hello";
secondWord = "World";

cout << firstWord << " " << secondWord << "!" << endl;

return 0;
}

Hello World!

https://redd.it/1okgox7
@r_cpp
Is this a correct implementation of Rust's Result enum for Arduino's C++ environment?

Hello Reddit!

Previously, I tried to recreate Rust's `Result` enum in C++ for the ESP32.

https://old.reddit.com/r/cpp/comments/1aifn5o/recreating_the_rust_result_enum_in_c_on_an_esp32/

But I have since realized that my old version kinda sucked!

For context, Arduino doesn't support most of the C++ standard library, but the ESP32 does.

What I really wanted was something you could just paste into the Arduino IDE and it would just work.
Now that I've rewritten it, it's possible!


However, I'm kind of sad to admit that I used AI (Google Gemini) to code a lot of this. Specifically:

* the [`std::remove_reference`], [`std::move`], and [`std::declval`] alternatives

* the [`auto`] and [`declval`] type shenanigans on the [`Result::match`], [`Result::map`] methods to get them to support lambdas. My original version only supported function pointers (see the code in the link above)!

* the other overloads of [`expect`] (I understand that `&` is a reference and `&&` is an rvalue reference (which is a basically thing that can be [`move`]d from?), but I still don't have quite the deep knowledge on it to write all the proper overloads, especially with those being after the function signature?)

* the improved versions of the [`Result`] type's copy and move constructors and its assignment operators (I didn't know about placement new before trying to rewrite the [`Result`] type, and it completely slipped my mind that you had to call the destructor if the [`other`] in the assignment operator was of a different tag!)

Of course, I've read through the code that the AI wrote and it seems logically correct to me, and I've rewritten a lot of it so that it's in my own coding style.

But because I've written it with AI, I don't really trust it.

Could I ask for you guys' help?
I'm only a beginner-intermediate C++ coder,
so is there anything wrong with the code that I don't see?

Thanks in advance!

```

#ifndef RESULT_HPP
#define RESULT_HPP

#include <new>

template<typename P>
void println(P printable);

[[noreturn]] void never() noexcept {
while (true) {
}
}

template <typename M>
[[noreturn]] void panic(M message) noexcept {
println(message);
never();
}

template<typename T> struct remove_reference {
using type = T;
};
template<typename T> struct remove_reference<T &> {
using type = T;
};
template<typename T> struct remove_reference< T && > {
using type = T;
};

template<typename T>
constexpr typename remove_reference<T>::type &&move(T &&arg) noexcept {
return static_cast< typename remove_reference<T>::type && >(arg);
}

template<typename T>
typename remove_reference<T>::type &&declval() noexcept;

template<typename T, typename E>
class Result {
private:
struct OkOverload {
};
struct ErrOverload {
};

public:
static Result ok(const T &ok) {
return Result{
Tag::Ok,
ok,
OkOverload{}
};
}

static Result ok(T &&ok) {
return Result{
Tag::Ok,
move(ok),
OkOverload{}
};
}

static Result err(const E &error) {
return Result{
Tag::Err,
error,
ErrOverload{}
};
}

static Result err(E &&error) {
return Result{
Tag::Err,
move(error),
ErrOverload{}
};
}

template<typename OnOk, typename OnErr>
auto match(OnOk on_ok, OnErr on_err) && -> decltype(on_ok(declval<T>())) {
switch (_tag) {
case Tag::Ok:
return on_ok(move(_value.ok));
case Tag::Err:
return on_err(move(_value.error));
default:
panic("[_tag] was left in an invalid state!");
}
}

template<typename OnOk, typename OnErr>
auto match(OnOk on_ok, OnErr on_err) const & -> decltype(on_ok(declval<const T &>()))
Including a header that declares/defines the same symbols and names as a module after that module, should be an error class of its own.

I was initially planning to phrase this as a question, but this is something I've bumped up against repeatedly while iterating on `vulkan.cppm`, and was wondering what the wider community thinks of this, which is quite a common error to stumble upon when working with an intermediate codebase that has both module imports and headers.

The standard as far as I can tell doesn't explicitly say anything about this, but de-facto compiler behaviour (GCC, MSVC) is to allow headers-before-modules, but disallow the reverse ordering.

I'd like to know what everyone thinks about disallowing any #include statements after an import statement in the global module fragment (GMF)—effectively splitting it into two segments, which would also solve this problem.

https://redd.it/1oub82l
@r_cpp
vcpkg and include folders for opencv

Hello all,

I've recently encountered a weird bug on my end.

Basically, when I install the opencv package, vcpkg copies the built library in this folder

.\vcpkg_installed\x86-windows\x86-windows\include\opencv2.4

This means, when I try to include the files in my code I have to write them like this:

#include <opencv2.4/opencv2/opencv.hpp>

Now if I try to build you can already imagine what happens. I get a compiler error telling my that inside opencv.hpp the following include #include "opencv2/opencv_modules.hpp" couldn't be resolved.

It makes sense since the folders opencv2 and opencv should be placed directly under the include folder.

Has anyone experienced this? Does anyone know how I could fix it without moving the folders by hand?

Thanks in advance!

PS: I already tried with the package opencv and it's the same. It puts the library under .\vcpkg_installed\x86-windows\x86-windows\include\opencv4\opencv2


Edit: I guess I can just modify my project properties to include that additional include directory. But then my question is, shouldn't vcpkg take care of this exactly?

https://redd.it/1oud8ct
@r_cpp
Cursed arithmetic left shifts

So I recently came across a scenario where I needed to set a single bit in a 64 bit value. Simple:

uint64t result = 1ull << n;

I expected to rely on result being zero when n is out of range (n >= 64). Technically, this is how an arithmetic and logical shift would behave, according to their definitions as per wikipedia and technically intels x86 manual. Practically this is not how they behave on our hardware at all and I think this is interesting to share.

So I wrote this little test to see what happens when you shift out of range:

#include <iostream>
#include <bitset>
#include <stdint.h>

int main()
{
uint64
t bitpattern = 0xF0FF0FF00FF0FF0Full;
// shift overflow
for (uint64t shift = 0;shift <= 128ull;shift++)
{
uint64
t shiftresult = bitpattern << shift;
std::bitset<64> bitset
result(shiftresult);
std::cout << bitset
result << " for a shift of " << shift << std::endl;
}
return 0;
}

And right at the threshold to 64 the output does something funny:

1111000011111111000011111111000000001111111100001111111100001111 for a shift of 0
1110000111111110000111111110000000011111111000011111111000011110 for a shift of 1
1100001111111100001111111100000000111111110000111111110000111100 for a shift of 2
...
1110000000000000000000000000000000000000000000000000000000000000 for a shift of 61
1100000000000000000000000000000000000000000000000000000000000000 for a shift of 62
1000000000000000000000000000000000000000000000000000000000000000 for a shift of 63
1111000011111111000011111111000000001111111100001111111100001111 for a shift of 64
1110000111111110000111111110000000011111111000011111111000011110 for a shift of 65
1100001111111100001111111100000000111111110000111111110000111100 for a shift of 66

...
1100000000000000000000000000000000000000000000000000000000000000 for a shift of 126
1000000000000000000000000000000000000000000000000000000000000000 for a shift of 127
1111000011111111000011111111000000001111111100001111111100001111 for a shift of 128

It behaves as if result = input << n % 64; !!

So, I did a little bit of digging and found that GCC uses the SAL instruction (arithmetic shift) to implement this. From what I gathered, when working with unsigned types the logical shift should be used but this is of no relevance as SAL and SHL are apparently equivalent on x86_64 machines (which I can confirm).

What is far more interesting is that these instructions seem to just ignore out of range shift operands. I guess CPU's are wired to siply just care about the bottom 6 significant digits (or 5 in the case of the 32 bit wide instruction equivalent, as this also happens with 32 bit values at n = 32.) Notably, it does not happen at n = 16 for 16 bit values, they still use the 32 bit range.

MSVC and clang both do insert an SHL (logical left shift) instead of a SAL but the result is the same.

Now, there is one thing that really tripped me when debugging this initially:

uint64t result = 0;
uint64
t n = 63;
result = 1ull << (n + 1); // result is 1
result = 1ull << 64; // result is 0 !?

So, apparently, when GCC was able to just precompute the expression it would come up with the wrong result. This might be a compiler bug? This also happens on clang, I didn't test it on MSVC.



Just something I thought was interesting sharing. Took me quite a while to figure out what was happening and where my bug came from. It really stumped me for a day

https://redd.it/1ow3g9y
@r_cpp
Anyone else decided to ditch the baby with the bathwater and redesign C++ to fit their needs?

Really long story short, Ive had this idea in my head forever for a UEFI application, but I keep running into roadblocks actually trying to debug it whenever I try to implement it.

C is a little too old and really missing proper QOL features like templates, constructors, name scoping, etc.

Rust is great but I want to beat my face in with a rake dealing with memory allocations and the lifetime system

Zig is nearly perfect. not quite convinced on the build system yet but with better documentation, im sure ill be convinced. However, its impossible to output DWARF debug info for PE/COFF targets as is UEFI. Plus alot of the debugging features are broken in UEFI targets so actually finding bugs is near impossible.

So I got left with C++, after tasting the real freedom that is modern languages. Since UEFI is essentially a freestanding target anyway so I dont get stdlib support. So I figured fuck it, lets design a stdlib to fit my own needs.

#include <efi/typedef.h>
#include <efi/status.h>


#include <allocate.h>
#include <exit.h>


#include <QEMU/debugCon.h>


extern "C" Status efi_main(EFI_HANDLE ImageHandle, SystemTable* st, void* imageBase) {
Allocator iface = poolAllocator(st);


if (Option<Slice<char>> result = iface.alloc<char>(14); result.isSome()) {
Slice<char> str = result.unwrap();
const char* lit = "Hello World!\n";
for (uintmax_t i = 0; i < str.len; i++) {
str[i] = lit[i];
}


DebugCon::putChars(0, lit);
DebugCon::putChars(0, str.ptr);


iface.free(str);
}


return Status::Success;
}

After fighting with the compiler/linker for 2 weeks to get a bootable & debuggable image where UEFI, GDB, and the compiler wouldnt complain. I was finally able to write a CRT0 runtime, and modify the linker script for constructors/deconstructors. Then implement all the UEFI base types/definitions for a bare minimal environment and to properly handle debugging. Then I could start to implement core types like slice<t> and option<t> to handle things like memory allocations via a consumable interface.

Its been a rough several weeks, but im finally at the point where the "standard" library I will be using is starting to take enough shape. Just to make the above code run properly without bugs is \~2500 lines of code lol.

https://redd.it/1p7zlou
@r_cpp
what do you think about this

\#include <iostream>



\#define print(x) std::cout << x;



int main() {

char x[\] = " hello";

print("im dave," << x)



return 0;

}


can this be a problem?

https://redd.it/1p9owjg
@r_cpp
[Open Source] IACore: A battery-included C++20 foundation library (IPC, Async, HTTP, Logging) to escape dependency hell.

Hey friends,

Like many of you, I grew tired of "C++ Dependency Hell".. Every time I started a new project (specifically game engines and dev tools), I found myself wasting days setting up the same glue code: finding an HTTP library, setting up a job system, wrestling with platform-specific IPC, and configuring a logger.

I wanted a "bedrock" library—something I could drop into any project and immediately have the essentials working, without linking 50 different `.lib` files manually.

So I built **IACore**. It started as the internal core library for my work at **IASoft**, but I realized it solves a problem almost every C++ dev faces. I’ve cleaned it up, added tests, and I'm open-sourcing it under GPLv3 today.

**What's inside?** It wraps "best-in-class" dependencies into a unified, coherent C++20 API. It manages its own deps via CMake `FetchContent`, so you don't need to install anything manually.

* ** IPC:** High-performance shared-memory ring buffers (wait-free SPSC).
* **🧵 Async:** A work-stealing job scheduler (High/Normal priority queues).
* **🌐 Networking:** A clean wrapper around `cpp-httplib` that handles Zlib/Gzip compression automatically.
* **📂 IO:** Memory-mapped file operations and optimized binary stream readers/writers.
* **🛠️ Modern:** Uses `std::span`, `tl::expected`, and C++20 concepts throughout.

**Where to get it:** [https://github.com/I-A-S/IACore](https://github.com/I-A-S/IACore)

Any and all feedback & questions are welcome! (Even the rude ones—I know how r/cpp can be sometimes 😆 ).

# Examples

**1. Async Tasks**

C++

#include <IACore/AsyncOps.hpp>

// Initialize worker threads (hardware_concurrency - 2)
IACore::AsyncOps::InitializeScheduler();

// Schedule a task
auto* mySchedule = new IACore::AsyncOps::Schedule();

IACore::AsyncOps::ScheduleTask([](auto workerID) {
printf("Running on worker %d\n", workerID);
}, 0, mySchedule);

// Wait for completion
IACore::AsyncOps::WaitForScheduleCompletion(mySchedule);

**2. HTTP Request**

C++

#include <IACore/HttpClient.hpp>

IACore::HttpClient client("https://api.example.com");
auto res = client.JsonGet<MyResponseStruct>("/data", {});

if (res) {
std::cout << "Data: " << res->value << "\n";
} else {
std::cerr << "Error: " << res.error() << "\n";
}

**3. IPC (Shared Memory Ring Buffer)**

*Manager:*

C++

#include <IACore/IPC.hpp>

// Spawns a child process and connects via Shared Memory
auto nodeID = manager.SpawnNode("MyChildNodeExe");
manager.WaitTillNodeIsOnline(*nodeID);

// Send data with zero-copy overhead
String msg = "Hello Node";
manager.SendPacket(*nodeID, 100, {(PCUINT8)msg.data(), msg.size()});

*Node:*

C++

#include <IACore/IPC.hpp>

class Node : public IACore::IPC_Node {
public:
void OnSignal(uint8_t signal) override {
// Handle signals
}

void OnPacket(uint16_t packetID, std::span<const uint8_t> payload) override {
// Handle packets
}
};

int main(int argc, char* argv[]) {
// The connection string is passed as the first argument by the Manager
if (argc < 2) return -1;

Node node;
// Connect back to the manager via Shared Memory
if (!node.Connect(argv[1])) return -1;

while(true) {
node.Update();
}
return 0;
}

https://redd.it/1pni3y8
@r_cpp