how to initialize a large size of std::array - c++

i have a class,the class contains a large size of std::array,how to initialize the array??
see class test;
sample:
class context{......}
class value
{
public:
value(context& ctx) : ctx_(ctx){
}
protected:
context& ctx_;
int data_ = 0;
}
class test
{
public:
test() : /*i need to initialize values at here*/ values_{ctx_,.....}
{
}
protected:
context ctx_;
std::array<value_t,10000> values_;
}
in reality,this array maybe only contains 3 or 5 element,not 10000,but someof people definitely gonna give me an answer like below
test() : values_{ctx_,ctx_,ctx_,ctx_,ctx_}
{
}
i don't need a awkward answer like above.
is there a way to initialize std::array with simple code like fold expression???

You can delegate to a constructor that takes a parameter pack then fold over that:
#include <utility>
#include <cstddef>
class test
{
public:
test() : test(std::make_index_sequence<10000>{}) {}
private:
template<std::size_t... I>
test(std::index_sequence<I...>) : values_{{(I, ctx_)...}} {}
protected:
context ctx_;
std::array<value_t, 10000> values_;
};
Though this absolutely killed compile time at any level of optimisation other than -O0 for me (And will probably blow up your compiled code size)
You could also try constructing into uninitialised memory so you don't need to default construct:
#include <array>
#include <cstddef>
#include <new>
#include <memory>
class test
{
public:
test() {
std::byte* p = value_memory_;
for (std::byte* end = std::end(value_memory_); p < end; p += sizeof(value_t)) {
new (p) value_t(ctx_);
}
}
~test() {
value_t* values = get_values();
std::destroy(values, values + 10000);
}
protected:
context ctx_;
value_t* get_values() {
return std::launder(reinterpret_cast<value_t*>(value_memory_));
}
const value_t* get_values() const {
return std::launder(reinterpret_cast<const value_t*>(value_memory_));
}
// These are UB, but work on most compilers, and would generally be nicer
// to work with
value_t(&get_values())[10000] {
return *std::launder(reinterpret_cast<value_t(*)[10000]>(value_memory_));
}
const value_t(&get_values() const)[10000] {
return *std::launder(reinterpret_cast<const value_t(*)[10000]>(value_memory_));
}
private:
alignas(value_t) std::byte value_memory_[sizeof(value_t) * 10000u];
};
Which will have some runtime cost, and you have to lose the std::array (Unless you go for a std::array<std::aligned_storage_t<sizeof(value_t), alignof(value_t)>, 10000>, in which case you have to launder every single element of the array)

The problem is that your array holds elements of a type that does not have a default constructor, so when you declare a std::array holding that type, the array can only be initialized using aggregate initialization so you can explicitly pass in a value to each element's constructor. When the array is a member of a class or struct, that initialization requires use of the class/struct constructor's member initialization list. Exactly what you are trying to avoid.
To get around this, you can use placement-new to explicitly construct each array element individually in a loop:
#include <type_traits>
class context{......}
class value
{
public:
value(context& ctx) : ctx_(ctx){
}
protected:
context& ctx_;
int data_ = 0;
}
class test
{
public:
test()
{
for (auto &v : values_)
new (&v) value(ctx_);
}
~test()
{
for (auto &v : values_) {
// note: needs std::launder in C++17 and later
// std::launder(reinterpret_cast<value*>(&v))->~value();
reinterpret_cast<value*>(&v)->~value();
}
}
protected:
context ctx_;
using storage_type = std::aligned_storage<sizeof(value), alignof(value)>::type;
std::array<storage_type, 10000> values_;
// Access an object in aligned storage
value& operator[](std::size_t pos)
{
// note: needs std::launder in C++17 and later
// return *std::launder(reinterpret_cast<value*>(&values_[pos]));
return *reinterpret_cast<value*>(&values_[pos]);
}
};

You can use fill() method on the array:
https://en.cppreference.com/w/cpp/container/array/fill

Related

C++ choose template type of class member in constructor

I'm trying to define template class inside of nontemplate class, below you may see the code of what i'm actually trying to do (it doesn't compilable for obvious reason). The main question is how can I realize that using C++11 (preferable) or C++14?
Actually I've got solution using std::variant or same function from the BOOST library, but I need to know another way to solve that.
I found old similar question, and answer by Anne Quinn sounds valuable (he suggest to declare subclasses for each type I need), but how to apply that in code right?
Code:
#include <vector>
#include <cstdint>
enum Type {
INT16,
UINT32
};
template<typename T>
class Buffer {
public:
Buffer(uint32_t paramSize) {
buffer.resize(paramSize);
}
private:
std::vector<T> buffer;
};
class Foo {
public:
Foo(Type paramType, uint32_t paramSize) {
switch(paramType) {
case UINT32:
buffer = Buffer<uint32_t>(paramSize);
break;
case INT16:
buffer = Buffer<int16_t>(paramSize);
break;
}
}
private:
Buffer buffer;
};
int main() {
Foo var(INT16, 30);
return 0;
}
UPD1: answer by #user2308211 seems work, but I got two problems with that. In case I'm copying object Foo and original object destroys for some reason (moving out of scope for example), copy will stay with pointer to nowhere. Second one is how to retrieve my buffer through Foo class.
UPD2: shared_ptr resolves problem with copying, but then copy will store the same object, in case you wanna modify them independently, use copy constructor as shown in answer. As for access to original buffer, void pointer allow you to retrieve pointer to vector, then you should static_cast it to your type.
Thanks!
Have a base class with all the required functions for Buffer as pure virtual.
#include <vector>
#include <cstdint>
enum Type {
INT16,
UINT32
};
class BufferBase {
public:
virtual void someFn()=0;
virtual ~BufferBase() {}
};
template<typename T>
class Buffer:public BufferBase {
public:
Buffer(uint32_t paramSize) {
buffer.resize(paramSize);
}
void someFn() override {
//functionality.
}
~Buffer() {}
private:
std::vector<T> buffer;
};
class Foo {
public:
Foo(Type paramType, uint32_t paramSize) {
this->bufferType = paramType;
switch(paramType) {
case UINT32:
buffer = new Buffer<uint32_t>(paramSize);
break;
case INT16:
buffer = new Buffer<int16_t>(paramSize);
break;
}
}
~Foo() {
delete this->buffer;
}
Foo &operator=(const Foo &other) {
this->bufferType = other.bufferType;
switch(bufferType) {
case UINT32:
buffer = new Buffer<uint32_t>(*static_cast<Buffer<uint32_t>*>(other.buffer));
break;
case INT16:
buffer = new Buffer<int16_t>(*static_cast<Buffer<int16_t>*>(other.buffer));
break;
}
return *this;
}
Foo(const Foo &other) {
*this=other;
}
private:
BufferBase *buffer;
Type bufferType;
};
int main() {
Foo var1(INT16, 30), var2(UINT32, 25);
var1 = var2;
return 0;
}
EDIT: I've updated the answer with a copy constructor.

C++ OOP: Class knows its index in the container - prevent overwrite?

I have a class idx_aware that goes into a container container, which wraps around a std::vector. When the class is added to container, container sets a pointer to itself in idx_aware, as well as the index of idx_aware in its internal memory storage.
The index is not going to change until the container is destroyed or idx_aware is removed; idx_aware needs to know about its container and its index, because it has some methods that require both to work.
Now this introduces the following problem: when I get a non-const reference to an idx_aware class contained in container, I could assign to it another idx_aware class, which could have a different index. The intention would be assigning all the fields and keeping the index as it is.
#include <vector>
#include <limits>
#include <iostream>
class container;
// Stores a std::size_t field, which can be set only by subclasses.
class with_idx {
std::size_t _i;
public:
with_idx() : _i(std::numeric_limits<std::size_t>::max()) {}
operator std::size_t() const { return _i; }
protected:
void set_idx(std::size_t i) { _i = i; }
};
// Knows its index and its container
class idx_aware : public with_idx {
container const *_container;
int _some_field1;
float _some_field2;
public:
void foo() {
// Do stuff using _container and _i
}
private:
friend class container;
};
// Wraps around a std::vector
class container {
std::vector<idx_aware> _data;
public:
idx_aware &operator[](std::size_t idx) {
// Need non-const access to call foo
return _data[idx];
}
idx_aware const &operator[](std::size_t idx) const {
return _data[idx];
}
std::size_t add(idx_aware const &item) {
// Here it could potentially reuse a freed position
std::size_t free_slot = _data.size();
// Ensure _data is big enough to contain free_slot
if (_data.size() <= free_slot) {
_data.resize(free_slot + 1);
}
// Assign
_data[free_slot] = item;
_data[free_slot].set_idx(free_slot);
_data[free_slot]._container = this;
return free_slot;
}
};
int main() {
container c;
idx_aware an_item;
std::size_t i = c.add(an_item);
std::cout << c[i] << std::endl; // Prints 0
idx_aware another_item; // Created from somewhere else
// I want to set all the data in idx_aware, but the
// index should stay the same!
c[i] = another_item;
std::cout << c[i] << std::endl; // Prints numeric_limits<size_t>::max()
// Now container[i] is broken because it doesn't know anymore its index.
return 0;
}
One possible workaround would be to change with_idx in such a way that when set_idx is called, a flag is set that prevents assignment and copy operator to overwrite the _i property, like this:
class with_idx {
std::size_t _i;
bool _readonly;
public:
with_idx() : _i(std::numeric_limits<std::size_t>::max()), _readonly(false) {}
with_idx(with_idx const &other) : _i(other._i), _readonly(false) {}
with_idx &operator=(with_idx const &other) {
if (!_readonly) {
_i = other._i;
}
return *this;
}
operator std::size_t() const { return _i; }
protected:
void set_idx(std::size_t i) {
_i = i;
if (i != std::numeric_limits<std::size_t>::max()) {
// This has been set by someone with the right to do so,
// prevent overwriting
_readonly = true;
} else {
// Removed from the container, allow overwriting
_readonly = false;
}
}
};
This would have the consequence of returning, after assignment, a reference to an idx_aware class with unchanged index.
idx_aware &not_in_container1 = /* ... */;
idx_aware &not_in_container2 = /* ... */;
idx_aware &in_container = /* ... */;
not_in_container1 = in_container = not_in_container2;
// std::size_t(not_in_container_1) != std::size_t(not_in_container_2)
Is there a design pattern that can model this situation in a better way? My searches were not successful.
Are there other unwanted consequences of overriding the assignment operator in this way? The limitation I pointed out in the previous example does not look too "bad".
Is there an easier solution? I thought about writing some proxy object to replace the idx_aware & return type of operator[].
Experience tells that when C++ does not do what you intend, you are likely to be misusing OOP...
Robert's comment suggested me this solution.
Why would the contained object know about its container? To be able to perform actions such as foo and provide shorthand methods that otherwise would require to have access to the container.
Let's take this functionality away from the contained object; the contained object is just data payload. Instead, let's make operator[] return not the contained object, but some sort of iterator, a wrapper around the contained object, which knows the container and the index, and once dereferenced returns the actual contained object.
class was_idx_aware {
int _some_field1;
float _some_field2;
};
class container {
std::vector<idx_aware> _data;
public:
class idx_aware_wrapper {
container const *_container;
std::size_t _idx;
public:
idx_aware_wrapper(container const &c, std::size_t i)
: _container(&c)
, _idx(i)
{}
was_idx_aware const &operator*() const {
return _container->_data[_idx];
}
was_idx_aware &operator*() {
return _container->_data[_idx];
}
void foo() {
// Do stuff using _container and _idx.
}
};
idx_aware_wrapper operator[](std::size_t i) {
return idx_aware_wrapper(*this, i);
}
/* .... */
};
This allows quick access to any data in was_idx_aware, and the wrapper class can be augmented with all the methods that require interaction with the container. No need to store and keep indices up to date or override assignment operators.

Initialization of anonymous class member variable with std::function

I wonder if there is a workaround is such situation:
class A
{
class
{
public:
void setValue(int val) {i=val;}
private:
int i;
} B = initB(10);
std::function<decltype(B)(int)> initB = [this](int value)
{decltype(B) temp;
temp.setValue(value);
return temp;};
}
//...
A a; //crash
//...
I suppose it is caused by order of initialization. Variable B is initilized by calling an uninitilized std::function instance, hence the crash. By my logic, the workaround would be to initialize std::function first, then initialize member B. But then, such code is not valid:
class A
{
//error: 'B' was not declared in this scope
std::function<decltype(B)(int)> initB = [this](int value)
{decltype(B) temp;
temp.setValue(value);
return temp;};
class
{
public:
void setValue(int val) {i=val;}
private:
int i;
} B = initB(10);
}
I tried to make to make the std::function static, and such code works, but requires non-constexpr/const member, because std::function has non-trivial destructor - which is bad, because that requires source file, which requires creating such file, which requires some efford and destruction of my beautiful header-only class hierarchy! (I mean, I could be lazy and define this variable in the header, but then the multiple definition problem occurs). I know it might be a bad design (i'm just testing things out), but do you have any ideas how the problem can be solved without involving source files?
Although your example is contrived, there are times when I've needed (or its more convenient) to initialize complex objects in a similar way.
But, why use std::function<>? Why not just use a function?
class A
{
class
{
public:
void setValue(int val) { i = val; }
private:
int i;
} B = initB(10);
static decltype(B) initB(int value)
{
decltype(B) temp;
temp.setValue(value);
return temp;
}
};
Although, I wouldn't normally use decltype(B); I would just give the class a name.
I feel like I am somehow subverting your intent, but if you initialize the variables in the constructor, you can make things work.
#include <functional>
class A
{
class
{
public:
void setValue(int val) {i=val;}
private:
int i;
} B;
std::function<decltype(B)(int)> initB;
public:
A() {
initB = [this](int value)
{decltype(B) temp;
temp.setValue(value);
return temp;};
B = initB(10);
}
};
int main() {
A a;
}
A::initB is a value. It's not initialized at the point where you call it, because initialization is done (loosely speaking) in the order you specify member fields. You can verify this by executing the below, which works:
#include <iostream>
#include <functional>
using namespace std;
template<typename T, typename U>
T set(T& tgt, const U& src)
{
new(&tgt) T(src);
return tgt;
}
class A
{
class
{
public:
void setValue(int val) {i=val;}
private:
int i;
} B = set(initB, [this](int value)
{decltype(B) temp;
temp.setValue(value);
return temp;})(10);
std::function<decltype(B)(int)> initB;
};
int main() {
A a;
}

C++ constructor: Initialize local variable before initializer list

How to store temporary state, needed for the initializer list, in the constructor (on the stack)?
For example, implementing this constructor …
// configabstraction.h
#include <istream>
class ConfigAbstraction
{
public:
ConfigAbstraction(std::istream& input);
private:
int m_x;
int m_y;
int m_z;
};
… using a stateful helper class like this?
// mysillyparserdontworry.h
#include <json/reader.h> //jsoncpp
class MySillyParserDontWorry
{
public:
MySillyParserDontWorry(std::istream& input) { input >> m_parseTree; }
int intByName(const char* name) const { return m_parseTree[name].asInt(); }
private:
Json::Value m_parseTree;
};
My attempt:
// configabstraction.cpp
ConfigAbstraction::ConfigAbstraction(std::istream& input)
: local_parserState(input) // init local variable first: Not possible!
, m_a(local_parserState.intByName("a"))
, m_b(local_parserState.intByName("b"))
, m_c(local_parserState.intByName("c"))
{
MySillyParserDontWorry local_parserState; // ...because it is local
}
With C++11 you could solve this with delegating constructors:
class ConfigAbstraction
{
public:
ConfigAbstraction(std::istream& input);
private:
ConfigAbstraction(const MySillyParserDontWorry& parser);
int m_a;
int m_b;
int m_c;
};
ConfigAbstraction::ConfigAbstraction(const MySillyParserDontWorry& parser)
: m_a{parser.intByName("a")}
, m_b{parser.intByName("b")}
, m_c{parser.intByName("c")}
{
}
ConfigAbstraction::ConfigAbstraction(std::istream& input)
: ConfigAbstraction{MySillyParserDontWorry{input}}
{
}
An alternative solution to your problem would be packing the three individual ints into a common data structure. This would allow you to initialise an object of that type with a private static helper function. Being able to initialise the object instead of assigning to it later also allows for it to be const (if that is required).
Here is an example with std::tuple. But you could also create your own helper struct or even std::array<int, 3>; the basic idea remains the same: have one member object instead of three.
#include <istream>
#include <tuple>
class MySillyParserDontWorry
{
public:
MySillyParserDontWorry(std::istream& input) { /* ... */ }
int intByName(const char* name) const { return /* ... */ 0; }
};
class ConfigAbstraction
{
public:
ConfigAbstraction(std::istream& input);
private:
static std::tuple<int, int, int> parse(std::istream& input)
{
std::tuple<int, int, int> result;
MySillyParserDontWorry parser(input);
std::get<0>(result) = parser.intByName("a");
std::get<1>(result) = parser.intByName("b");
std::get<2>(result) = parser.intByName("c");
return result;
}
std::tuple<int, int, int> const m;
};
ConfigAbstraction::ConfigAbstraction(std::istream& input)
: m(parse(input))
{
}
Why not simply doing the assignments in the constructor's body then?
ConfigAbstraction::ConfigAbstraction(std::istream& input)
: m_a(0)
, m_b(0)
, m_c(0)
{
MySillyParserDontWorry local_parserState;
m_a = local_parserState.intByName("a");
m_b = local_parserState.intByName("b");
m_c = local_parserState.intByName("c");
}
Is there any specific requirement that hinders you doing that?
What an artificial limitation of C++!
It's not an artificial limitation. How should initialisation of local variables be done outside of their function's scope? It would just lead to a great confusion, where variables are actually initialised (naming conflicts aside).
You can not initialize local variables bedfore members. The reason for this is very simple (so that it is NOT an artificial limitation):
Members have to be initialized (constructed) before constructor body begins, because constructor body might access them - and they need to be initialized for this access. On the other hand, local variables do not exist before code enters constructor body (as for any other function).
Conclusion - initialization of local variables before members is impossible.

How to get rid of weak_ptrs in a container

I have a class that stores weak_ptrs in a container and later does something if the weak_ptr is not expired:
class Example
{
public:
void fill(std::shared_ptr<int> thing)
{
member.push_back(thing);
}
void dosomething() const
{
for (const auto& i : member)
if (!i.expired())
;// do something. the weak_ptr will not be locked
}
private:
std::vector<std::weak_ptr<int>> member;
};
If Example is an object that lives forever and fill is used regularily, the vector allocates memory for elements continously, but they are never removed after they expired.
Is there any automatic C++ way to get rid of the expired weak_ptrs in the container or is there a better way to store a variable number of them?
My naive way would be to iterate over the container each time fill is called and remove all the expired weak_ptrs. In scenarios where Example has many elements in the container and fill is frequently called this seems to be very inefficient.
Since you clarified that you are actually using a std::map and not a std::vector, it might be easiest to remove the expired elements on-the-fly in doSomething(). Switch back from a range-based for loop to a normal iterator based design:
void dosomething() const
{
auto i = member.begin();
while( i != member.end() ) {
if( i->expired() ) { i = member.erase( i ); continue; }
;// do something. the weak_ptr will not be locked
++i;
}
}
Does the shared_ptr<int> have to be a shared_ptr<int>?
How about a shared_ptr<IntWrapper>?
#include <iostream>
#include <forward_list>
using namespace std;
class IntWrapper {
public:
int i;
static forward_list<IntWrapper*>& all() {
static forward_list<IntWrapper*> intWrappers;
return intWrappers;
}
IntWrapper(int i) : i(i) {
all().push_front(this);
}
~IntWrapper() {
all().remove(this);
}
};
void DoSomething() {
for(auto iw : IntWrapper::all()) {
cout << iw->i << endl;
}
}
int main(int argc, char *argv[]) {
shared_ptr<IntWrapper> a = make_shared<IntWrapper>(1);
shared_ptr<IntWrapper> b = make_shared<IntWrapper>(2);
shared_ptr<IntWrapper> c = make_shared<IntWrapper>(3);
DoSomething();
return 0;
}
I would rather use a custom deleter for the shared_ptr. But this implies here to change the interface of the Example class. The advantage using custom deleter is that there is no need to check for expired objects in the collection. The collection is directly maintained by the custom deleter.
Quick implementation :
#include <memory>
#include <iostream>
#include <set>
template <typename Container>
// requires Container to be an associative container type with key type
// a raw pointer type
class Deleter {
Container* c;
public:
Deleter(Container& c) : c(&c) {}
using key_type = typename Container::key_type;
void operator()(key_type ptr) {
c->erase(ptr);
delete ptr;
}
};
class Example {
public:
// cannot change the custom deleter of an existing shared_ptr
// so i changed the interface here to take a unique_ptr instead
std::shared_ptr<int> fill(std::unique_ptr<int> thing) {
std::shared_ptr<int> managed_thing(thing.release(), Deleter<containter_type>(member));
member.insert(managed_thing.get());
return managed_thing;
}
void dosomething() const {
// we don't need to check for expired pointers
for (const auto & i : member)
std::cout << *i << ", ";
std::cout << std::endl;
}
using containter_type = std::set<int*>;
private:
containter_type member;
};
int main()
{
Example example;
auto one = example.fill(std::unique_ptr<int>(new int(1)));
auto two = example.fill(std::unique_ptr<int>(new int(2)));
auto three = example.fill(std::unique_ptr<int>(new int(3)));
example.dosomething();
three.reset();
example.dosomething();
}