In C++, you can declare an array of something at the file scope:
static foo a[] = { foo(), foo(), foo() };
The individual foo objects have static storage (i.e. they are not allocated at run-time).
If I had a base class inherited by two or more derived classes, the following would compile but not work as expected due to slicing:
static base a[] = { derived1(), derived2() };
Something like this should not cause slicing to happen:
static derived1 d1;
static derived2 d2;
static base *a[] = { &d1, &d2 };
My question is: How can I do the same without having to declare d1
and d2
separately from a
, and while keeping static storage for the individual (pointed-to) elements? The following gives a "taking address of temporary" error:
static base *a[] = { &derived1(), &derived2() };
Maybe it would be possible to define a constexpr
variadic template function? Something like:
template<typename... Args>
constexpr std::initializer_list<base *> base_array(Args... args) {
...
}
Then I could write:
static base *a[] = base_ptr_array(derived1(), derived2());
Maybe this would have the same "taking address of temporary" problem, though my idea was that since this is a constexpr it would work similarly to { foo(), foo(), foo() }
above (which doesn't create temporaries).
You can use some template to avoid declaring those static variables:
#include <tuple>
#include <array>
#include <type_traits>
#include <utility>
template<class Base, class... Ts>
struct foo {
foo()
: foo(Ts{}..., std::index_sequence_for<Ts...>{})
{}
std::tuple<Ts...> deriveds;
std::array<Base*, sizeof...(Ts)> arr;
private:
template<std::size_t... Is>
foo(Ts... ts, std::index_sequence<Is...>)
: deriveds(ts...)
, arr{ &std::get<Is>(deriveds)...}
{}
};
// test
#include <iostream>
struct A {
virtual void show() const {
std::cout << "A\n";
}
virtual ~A() = default;
};
struct B: public A
{
void show() const override {
std::cout << "B\n";
}
};
struct C: public A
{
void show() const override {
std::cout << "C\n";
}
};
foo<A, A, B, C> f;
int main() {
for ( A *ptr : f.arr ) {
ptr->show();
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With