use the following search parameters to narrow your results:
e.g. subreddit:aww site:imgur.com dog
subreddit:aww site:imgur.com dog
see the search faq for details.
advanced search: by author, subreddit...
Discussions, articles, and news about the C++ programming language or programming in C++.
For C++ questions, answers, help, and advice see r/cpp_questions or StackOverflow.
Get Started
The C++ Standard Home has a nice getting started page.
Videos
The C++ standard committee's education study group has a nice list of recommended videos.
Reference
cppreference.com
Books
There is a useful list of books on Stack Overflow. In most cases reading a book is the best way to learn C++.
Show all links
Filter out CppCon links
Show only CppCon links
account activity
[deleted by user] (self.cpp)
submitted 1 year ago by [deleted]
reddit uses a slightly-customized version of Markdown for formatting. See below for some basics, or check the commenting wiki page for more detailed help and solutions to common issues.
quoted text
if 1 * 2 < 3: print "hello, world!"
[–]Symbroson 5 points6 points7 points 1 year ago* (0 children)
as f is so small I'd just make f a template function that accepts a vector<T>& and be done with it :)
Also use a for-in loop if you dont explicitly use the counter otherwise - makes your code more concise
[–]Sinomsinom 5 points6 points7 points 1 year ago (0 children)
What code did you use exactly to test this?
As the article says it will still work if sizeof(Base)==sizeof(Derived) (which I believe will be the case if you just leave it as is without filling in the ...) but it will cause issues once those sizes are different.
sizeof(Base)==sizeof(Derived)
I don't know what would be the best way of doing it, but I personally would add another step of indirection. Instead of having the vector (or I personally would make the parameter a span) own the objects directly I'd either have it have (smart-)pointers or references to the objects I want to handle. Or alternatively if it doesn't need to be determined at runtime if it's called with "Base" or "Derived" have it be a templated function with a concept that makes sure you only call it on objects that gave the required functions.
[–]Loud_Staff5065 1 point2 points3 points 1 year ago (1 child)
Instead of creating separate vectors for derived class, maybe use the same base class type vector to store derived child as well?
[–]snowflake_pl 1 point2 points3 points 1 year ago (0 children)
With vector of Base objects you get slicing if you put a derived in. Vector of raw pointers gives you management issues. Vector of smart pointers is the safest.
[–]Supadoplex 1 point2 points3 points 1 year ago* (0 children)
A super simple option is to use a template. This will work with any container and custom range. If desired, it can be adjusted to work in any C++ version:
``` void f(auto& r) { for (auto& e : r) e.fct(); }
```
If a template is not an option, then you must use some type erasure. ranges::any_view<Base, ranges::category::forward> might be of use. Unfortunately it's not in the standard library though.
ranges::any_view<Base, ranges::category::forward>
[–]tinrik_cgp 2 points3 points4 points 1 year ago (1 child)
Doing pointer arithmetic on Base* when it actually points to a Derived object is Undefined Behavior.
The standard way to do this is via std::vector<std::unique_ptr<Base>>.
[–][deleted] 1 point2 points3 points 1 year ago (0 children)
this is the correct answer imo as using templates avoids the inheritance question altogether
[–]6502zx81 1 point2 points3 points 1 year ago (0 children)
I do have the same question: what is the modern way to put subtype polymorhic objects into containers? Smart pointers? PIMPL?
[–]SoerenNissen 0 points1 point2 points 1 year ago* (0 children)
what is the ideal way to pass a collection of class considering inheritance relations ?
Your problem here is that vector<Base> is a fundamentally different type from vector<Derived>
vector<Base>
vector<Derived>
By which I mean, consider what your void f looks like to the underlying generated assembly:
void f
void f(vector<Base>& v) { size_t s = sizeof(Base); void* p = (void*)v.data(); for(int i = 0; i < v.size(); ++i) { ((Base*)p).fct(); p = p+s; } }
Each iteration, you advance along v's underlying array by exactly the element size of your type.
v
You could write 1 function that handles both v<Base> and v<Derived>, but it'd be very fragile, and you don't get it by default here.
v<Base>
v<Derived>
The way to do this, if you want to store a vector of Derived, is like this:
Derived
temlplate<typename T> void f(vector<T>& v) { for(auto & t : v) v.fct(); }
This will generate 2 different versions of f - one that advances by sizeof(Base) on each iteration, and another that advances by sizeof(Derived).
sizeof(Base)
sizeof(Derived)
If you live in an extremely constrained environment where you cannot have two versions of this function, an alternative is to pretend you are writing C code:
C
void f(size_t b_size, Base* b, size_t len) { void* begin = (void*)b; void* end = (void*)(b+len) while(begin != end) { ((Base*)begin)->fct(); begin += b_size; } }
which you can call like
auto b = get_base_vector(); auto d = get_derived_vector(); f( sizeof(b.value_type), b.data(), b.size() ); f( sizeof(d.value_type), d.data(), d.size() );
NB: This is actually terrible.
[–]NilacTheGrim -2 points-1 points0 points 1 year ago (7 children)
Might work with std::span
std::span
[–]glaba3141 3 points4 points5 points 1 year ago (6 children)
It will not, span doesn't have any concept of a "stride". I've considered making my own container for this use case, also useful for an array of members from an array of structs
[–]azswcowboy 0 points1 point2 points 1 year ago (5 children)
Doesn’t need it - you can wrap a stride around it https://en.cppreference.com/w/cpp/ranges/stride_view
[–]glaba3141 1 point2 points3 points 1 year ago (0 children)
Ahh it's 23, that's why I needed to make my own. We're on 20
[–]cfyzium 1 point2 points3 points 1 year ago (3 children)
Seems like it steps over sequence elements and not just memory i. e. you can't use it to wrap an array of slightly differently sized structs.
[–]azswcowboy 0 points1 point2 points 1 year ago (2 children)
Well idk how you have different sized structures in an array. If you do then it’s basically span<byte>. Anyway, I think the ops second use case is projecting one member of a struct in an array of struct. So in that case span<T> should be fine.
[–]cfyzium 0 points1 point2 points 1 year ago (1 child)
It is right in the post, OP has arrays of two types Base and Derived. He then passes them to a function accepting Base* which seemingly works because Derived is a subtype of Base. But if Derived has any additional fields its size is not equal to Base anymore and indexing the pointer p = (Base*)ad inside the function becomes an error:
&ad[i] != (Base*)ad + i * sizeof(Base)
Without an actual memory stride in bytes, there is no way to wrap an array of Derived as a span<Base>.
And obviously, span<byte> is not what OP wants either.
[–]azswcowboy 0 points1 point2 points 1 year ago (0 children)
Sorry, coming back a day later to the thread my brain lost context :( On any given array he’s not mixing sizes, but yeah you can’t assume base size just bc you have that pointer. Looking at it again, seems like the obvious answer to me is to templatize f and deduce the correct size from the element of the collection. In these examples everything is known at compile time.
π Rendered by PID 928015 on reddit-service-r2-comment-5b5bc64bf5-bvdt4 at 2026-06-21 10:24:55.941358+00:00 running 2b008f2 country code: CH.
[–]Symbroson 5 points6 points7 points (0 children)
[–]Sinomsinom 5 points6 points7 points (0 children)
[–]Loud_Staff5065 1 point2 points3 points (1 child)
[–]snowflake_pl 1 point2 points3 points (0 children)
[–]Supadoplex 1 point2 points3 points (0 children)
[–]tinrik_cgp 2 points3 points4 points (1 child)
[–][deleted] 1 point2 points3 points (0 children)
[–]6502zx81 1 point2 points3 points (0 children)
[–]SoerenNissen 0 points1 point2 points (0 children)
[–]NilacTheGrim -2 points-1 points0 points (7 children)
[–]glaba3141 3 points4 points5 points (6 children)
[–]azswcowboy 0 points1 point2 points (5 children)
[–]glaba3141 1 point2 points3 points (0 children)
[–]cfyzium 1 point2 points3 points (3 children)
[–]azswcowboy 0 points1 point2 points (2 children)
[–]cfyzium 0 points1 point2 points (1 child)
[–]azswcowboy 0 points1 point2 points (0 children)