Suppose you have a class that operates on a vector:
class Foo{
public:
Foo() {
m_dynamic_data.push_back(5);
std::cout << m_dynamic_data[0] << std::endl;
}
private:
std::vector<int> m_dynamic_data;
};
In my case this class is huge with 2500 additional lines of code.
This class behaves dynamic (hence std::vector
). But I would also like to provide a "static" implementation (using std::array
). So std::size_t N
is added, which now should control when to use which attribute.
template<std::size_t N>
class Foo{
private:
std::vector<int> m_dynamic_data; //use this, when N == 0
std::array<int, N> m_static_data; //use this, when N != 0
};
I am not sure if I can get this to work. using #define
won't do the job (since it can't alternate). constexpr
can't be wrapped around two attributes either. The best solution is probably to provide a base class and then inherit the dynamic and static case from it. But before I spent the next days doing this, I wonder if there isn't a technique afterall.
I thought about putting both into a std::unique_ptr
and only constructing the relevant array:
template<std::size_t N>
class Foo {
public:
Foo() {
if constexpr (N) {
m_static_data_ptr = std::make_unique<std::array<int, N>>();
(*m_static_data_ptr)[0] = 5;
std::cout << (*m_static_data_ptr)[0] << std::endl;
}
else {
m_dynamic_data_ptr = std::make_unique<std::vector<int>>(1);
(*m_dynamic_data_ptr)[0] = 5;
std::cout << (*m_dynamic_data_ptr)[0] << std::endl;
}
}
private:
std::unique_ptr<std::vector<int>> m_dynamic_data_ptr;
std::unique_ptr<std::array<int, N>> m_static_data_ptr;
};
I earlier asked about this case here. But apparently this doesn't seem like a good approach. (fragmenting memory, cache miss rate). std::optional
also seems interesting, but it pushes the sizeof(Foo) too far for my goal.
Ultimately there is also using void
pointers:
template<std::size_t N>
class Foo {
public:
Foo() {
if constexpr (N) {
m_data = malloc(sizeof(std::array<int, N>));
(*static_cast<std::array<int, N>*>(m_data))[0] = 5;
std::cout << (*static_cast<std::array<int, N>*>(m_data))[0] << std::endl;
}
else {
m_data = new std::vector<int>;
(*static_cast<std::vector<int>*>(m_data)).push_back(5);
std::cout << (*static_cast<std::vector<int>*>(m_data))[0] << std::endl;
}
}
~Foo() {
delete[] m_data;
}
private:
void* m_data;
};
But this seems pretty dirty [...] So the goal would be to work with either array structure at compile time. Thanks for any help / suggestion!