Every now and then I come across a situation when I need to create an array of non-copy-constructible objects. For example:
std::vector<std::thread> thread_pool(NUM_CORES, std::thread(some_function));
That would be convenient. But alas, the std::vector fill constructor doesn't seem to have any support for R-values. It is defined as:
vector(
size_type count,
const T& value,
const Allocator& alloc = Allocator()
);
But it would be extremely convenient to have:
vector(
size_type count,
T&& value,
const Allocator& alloc = Allocator()
);
Then the vector could internally allocate the necessary buffer size, and move-construct each element with placement new.
But... the C++11 standard (and apparently even the C++14 standard) don't provide this capability. So, now - when I have a vector of threads, I have to say:
std::vector<std::unique_ptr<std::thread>> thread_pool(NUM_CORES);
/* now loop over vector and initialize elements one by one */
Is there some reason this ability was left out? Is there some danger? Or some problem that I'm not seeing?
What you propose is not feasible because, by its very nature, moving is the transfer of a state from one object to one other object. You cannot construct N objects by moving state from one to all of them at the same time.
The Stargate universe violated this rule by introducing the ability to open a wormhole to every gate in the galaxy simultaneously, which made no sense at all and really annoyed me. Don't be that guy!
A vector constructor looking like this:
template <typename T>
template <typename Args...>
std::vector<T>::vector(const size_t n, Args&&... args);
…following the emplace model could work, though I worry that it would be easy to get an ambiguous overload thanks to the sheer number of existing constructors for std::vector<T>. I suspect this is why it was not done, besides the fact that it isn't really necessary.
Because, for now, you can workaround it by emplacing one at a time which, regardless, is probably as performant as you can ever hope to get:
std::vector<std::thread> v;
v.reserve(NUM_CORES);
for ( /*...*/ )
v.emplace_back( /*...*/ );
Related
Back in '98 I converted my chemical model from objective-c to c++ after replacing my old NeXT, but I didn't really get a chance to learn c++. I'm now rewriting the code into modern c++, which means learning to use containers, smart pointers, and templates.
I need to parse output variables only once up front, rather than at each time step, so I originally produced a pointer array of output variable pointers (float ***outVars). I could run through the list of pointers after each time interval, and since outVars pointed to the original data, they would always provide the current state of the model.
I'm changing code from matrices of naked pointers to matrices of vectors. I haven't been able to return anything but copies of vectors, rather than references to the original vectors. I don't want to modify the vectors, I just need direct read access.
I can't believe I haven't found my answer online yet. Most that I've found online has simply said use std::vector<float> & to return by reference, but clearly that isn't working.
I saw one note that assigning a reference to a non-reference value (I assume they meant variable) will make it copy, so I tried fvec2D &outVar2D; (see the header file below).
I've tried with and without const, no difference.
I've tried returning vector.data(), but assigning it to a new vector was also copying. Maintaining pointers to .data() memory blocks seems be a very bad idea, if I need to resize the original vector.
I've tried wrapping the vector in std::shared_ptr, but found I'd need to wrap each dimension vector in a shared_ptr, which got overly cumbersome real fast.
I saw one suggestion to return vector::iterators. I haven't managed to get that to work yet. Maybe having 2D data is getting in the way of that. I'm still trying to get that to run without crashing when I examine the iterator.
I don't know if using a 1D array would solve this, but calculating every index reference for millions of calls seems suboptimal.
I considered using std::array too but vectors seemed the simplest conversion. Perhaps I should rethink that.
If anyone has any suggestions for how to do this, I'd very much appreciate it.
class chem - manages original matrix concentration
class chem
{
public:
typedef std::vector<float> fvec1D;
typedef std::vector<std::vector<float> > fvec2D;
chem(int xstep, int zstep) : concentration(xstep, fvec1D(zstep, 1.5)) {}
...
const fvec2D &getConc() const { return concentration; }
const fvec1D &getConc(int x) const {return concentration[x]; }
private:
fvec2D concentration;
};
class model - needs read access to chem::concentration
class model
{
public:
typedef std::vector<float> fvec1D;
typedef std::vector<std::vector<float> > fvec2D;
...
private:
fvec2D null2D {{0.0}};
fvec1D null1D {0.0};
fvec2D &outVar2D;// = null2D; // tried this and at ctor
fvec1D &outVar1D;// = null1D;
std::vector<std::unique_ptr<chem> > chemList;
};
model::model() : outVar2D(null2D), outVar1D(null1D)
{
outVar2D = chemList[0]->getConc(); // or
outVar1D = chemList[0]->getConc(1);
}
void model::plot()
{
for (int z=0; z<numZSteps; ++z) {
std::cout << outVar1D[z];
std::cout << outVar2D[1][z];
}
}
void model::run()
{
plot(); // produces init concentration of 1.5 at each z
chemList[0]->changeConc(); // Changes values in concentration
plot(); // STILL produces init conc of 1.5 at each z
}
I don't know if answering my own question is appropriate (please let me know). I know this question will be autodeleted, so I thought I'd present the solution I came up with, because I'm still VERY interested in hearing any suggestions of the best way to do this. I'm still so far down the learning curve I know I can't intuitively see c++ programming techniques.
I gathered from comments that what I was trying won't work, so I wrapped my vectors in shared_ptrs, which I know can work. I created some wrapper classes to manage 2 levels of shared_ptr (one for the multidimensional spatial data, and one for the list of output variables). It also keeps the array-type indexing intact as well as defines behavior for operator=.
I have only included the 2D classes here. I have 4 similar classes to handle the 1D and 3D cases as well.
I know what I'm posting is not great. it's not very elegant, requiring 2 classes for each dimensional case (1D, 2D, 3D data). Perhaps I can simplify it using templates. I've only written very elementary templates so far. Since each class decays (using operator[]) to a unique class I'm not sure if a template will help.
I haven't figured out all the const keyword placements yet - I removed them all for now, out of frustration with the compiler complaints. I'll get that down when I can take the time.
I also don't know exactly what sort of behavior I want for copy and move constructors, though I'm pretty sure I need them for vector resize operations, which I just realized I haven't even implemented yet. The important thing for me here was just to get read access to the vectors across classes, such that when the vectors change it is reflected elsewhere without re-parsing my output variables.
#include <memory>
#include <vector>
namespace MDType {
class fpv2D;
typedef std::vector<float> fvec1D;
typedef std::vector<std::vector<float> > fvec2D;
typedef std::vector<std::vector<std::vector<float> > > fvec3D;
typedef std::shared_ptr<fvec1D> fvec1Dptr;
typedef std::shared_ptr<fvec2D> fvec2Dptr;
typedef std::shared_ptr<fvec3D> fvec3Dptr;
typedef std::vector<fpv2D> fvpv2D;
typedef std::shared_ptr<fvpv2D> fvpv2Dptr;
class fpv2D
{
public:
fpv2D(int x=1, int z=1, float fill=0.0) : theArray(new fvec2D(x, fvec1D(z, fill))) {}
fpv2D(const fpv2D &otherT) = default; // Pretty sure this needs to change
fpv2D( fpv2D &&otherT) {theArray = otherT.data(); }
fvec2Dptr &data() { return theArray; }
fvec1D &operator[](int index) {return theArray->data()[index]; }
void operator=( fpv2D& rhs) { theArray = rhs.data(); }
private:
fvec2Dptr theArray;
};
class fpvpv2D
{
public:
fpvpv2D(int index, int x=1, int z=1, float fill=0.0) : theArray(new fvpv2D(index, fpv2D(x, z, fill))) {}
fpvpv2D(const fpvpv2D &otherT) = default; // Pretty sure this needs to change
fpvpv2D( fpvpv2D &&otherT) {theArray = otherT.data(); }
fvpv2Dptr &data() { return theArray; }
fpv2D &operator[](int index) {return theArray->data()[index]; }
void operator=( fpvpv2D& rhs) { theArray = rhs.data(); }
private:
fvpv2Dptr theArray;
};
}
... so ...
MDType::fpv2D conc(numX, numZ, 1.5);
MDType::fpvpv2D outVar2D(numOutVars, numX, numZ);
outVar2D[1] = conc;
cout << outVar2D[1][3][5]; // prints 1.5
conc[3][5] = 12.0;
cout << outVar2D[1][3][5]; // prints 12.0
It seems I am trying to fill a std::map with objects that are not copyable, and I have not achieved to do it yet.
General problem
I want to use std::map in order to store some objects of a type called Image (More precisely, it is Gdiplus::Image). I cannot write things like:
map<string, Gdiplus::Image> loadedImages ;
Gdiplus::Image newImage( CString("totoro.png") );
loadedImages.insert(std::pair<string, Gdiplus::Image>( "totoro", newImage ) );
Function "insert" seems to be the problem here. The compiler says:
'Gdiplus::Image::Image' : cannot access private member declared in class 'Gdiplus::Image'
I am not sure that it is the right explaination, but it seems that "Image" lacks of a public method used in function "insert". (Copy operator ? Copy constructor ?).
What I have tried
I tried to use references in the map, but it seems putting references in containers never works. I tried to use raw pointers, but I had got errors when I tried to delete all the images in the destructor. I happened across this other (and quite similar) question and I have begun to care about smart pointers. So now, I am trying, as recommended in the answer, with std::shared_ptr. However, my case is slightly different.
I want to write a function "find" that returns an image. "find" gives the image found in the map if the key (its path) exists, else it loads the image, add it to the map and returns it. So I cannot create a new image inside the parenthesis as I need the pointer.
The only version I came up with, that can compile is:
(Drawer.h)
#include <map>
#include <memory>
#include <Gdiplus.h>
using std::map ;
using std::shared_ptr ;
class CDrawer
{
public:
CDrawer(void);
~CDrawer(void);
void drawImage(string p_pathToPicture)
private:
map<string, shared_ptr<Gdiplus::Image>> m_loadedImages ; // Keep every image in memory instead of loading them each time. Each image has its path as a key.
Gdiplus::Image* findImage(string& p_path); // get the image from the map if the image is already loaded, else load it.
};
(Drawer.cpp) (Constructors and destructors are empty)
void CDrawer::drawImage(string p_pathToImage)
{
// get the bounding rectangle of the image
//...
Gdiplus::Image* l_image = findImage(p_pathToImage);
// Draw the image.
//...
}
Gdiplus::Image* CDrawer::findImage(string& p_pathToImage)
{
auto iterator = m_loadedImages.find(p_pathToImage);
if (iterator == m_loadedImages.end() ) // image not found, so we have not already loaded it
{
shared_ptr<Gdiplus::Image> l_newImage( new Gdiplus::Image( CString( p_pathToImage.c_str()) ) ); // Load the image (I know I have to add error code)
m_loadedImages.insert( std::pair<string, shared_ptr<Gdiplus::Image>>( p_pathToImage, l_newImage ) ); // Add the image to the list
return l_newImage.get() ;
}
else return iterator->second.get() ; // image found, so it is already loaded and we provide the existing one.
}
But it gives the following error during run time, when the destructor of Drawer is called:
Unhandled exception at 0x00C18CEE in MyProgramm.exe: 0xC0000005: Access violation reading location 0x02F36D78
Does someone knows where I am wrong, or if there is a simpler or better solution?
In my attempt to teach myself C++, I was hoping to get some help in how to read the const-ness of a expression/function etc. For example, the code below:
const screen &display(std::ostream &output) const {
do_display(output); return *this;
}
In the above code. there are two const declarations in the function display. In "English" how is that properly read? example: the first const is a const to reference or const to type screen? etc. and what exactly does the const-ness mean/imply when a reference is const etc. I have tried reading up on it but is still a bit muddy at this point.
Feel free to point to a youtube video or other reference material. Hopefully the material that is very clear.
I've always found that the simplest way to remember it is:
const applies to whatever is to the left of it, unless there isn't anything to the left of it, in which case it applies to whatever is to the right of it.
So, you have a const method that returns a const reference to a screen.
A const reference means you can't modify the referenced object. The const method means that the method won't modify the object it's being called on (the this pointer inside that method will be to a const object).
You read it right to left.
You have a constant method that returns a reference to a screen that is constant.
Returning a constant reference means you cannot modify what is returned.
If you call the method and assign it to some variable, the variable must use the const keyword. The only exception to this is if you cast the returned reference from the method to something that is not constant.
Here's a helpful link for more detail on the right to left rule:
http://ieng9.ucsd.edu/~cs30x/rt_lt.rule.html
That's actually written by a professor at UCSD (and he's pretty good).
The const on the right side of the method just means you can't modify any instance variables inside the function (for the most part). There's a bit more to it, but for more detail, refer to:
Meaning of "const" last in a C++ method declaration?
Read it right to left.
int const & foo() const
const method which returns a...
int const & foo() const
Reference to a...
int const & foo() const
const int.
The const can go on either side of int. You can read it as a "constant integer" or a "integer which is constant".
In English it means:
display() is a constant method of its class (this is the 2nd const keyword) that takes a reference to a std::ostream class instance as its parameter, and returns a reference to a constant (this is the 1st const keyword) instance of the screen class.
A const reference means that this reference cannot be used to modify the object being referenced. You can use the reference only to access, but not change, the members of the class, or to invoke the class's const methods (like display() is a const method of its own class).
Do I have to call delete on the destructor of a class that uses std::vectors ?
If not, why?
For example:
Test.h:
class Test
{
private:
// Signal buffer for RAW signal and Moving Average
std::vector<double> BUFFER; // Sensor signal buffer
...
}
Test.cpp:
#include "Test.h"
Test::~Test()
{
// no delete for std:vector as they use STD memory allocation ???
}
Test::Test()
{
BUFFER.reserve(100); // Who is going to free this memory?
}
Thanks
No you do not need to explicitly destroy or delete it. The vector is held by value in your class, so will be destroyed automatically, and the data inside the vector will be deleted by the vector's own destructor.
The term for all this is RAII, and it works really well.
No, you don't. You only use delete to match a use of new. Since (in this case) you used auto storage class, the vector will be deleted automatically when the Test that owns it is destroyed.
I'm trying to create a mutable dictionary that has weak-references for the value objects (the keys behave normally).
This is how i'm trying to do it:
+ (id)mutableDictionaryUsingWeakReferencesWithCapacity:(NSUInteger)capacity
{
CFDictionaryKeyCallBacks keyCallbacks = {0, CFRetain, CFRelease, CFCopyDescription, CFEqual, CFHash};
CFDictionaryValueCallBacks valueCallbacks = {0, NULL, NULL, CFCopyDescription, CFEqual};
id<NSObject> obj = (id)(CFDictionaryCreateMutable(NULL, capacity, &keyCallbacks, &valueCallbacks));
return [obj autorelease];
}
Unfortunately I get a warning (Initialization from incompatible pointer type)in when declaring the keyCallbacks, and i've tracked it down to using CFRetain and CFRelease. For some reason these callbacks do not match the required prototypes (CFDictionaryRetainCallback and CFDictionaryReleaseCallback)
In the documentation it says that an example CFDictionaryRetainCallback should look something like this:
const void *MyCallBack (
CFAllocatorRef allocator,
const void *value
);
But the existing CFRetain is declared as
CFTypeRef CFRetain(CFTypeRef cf);
It's missing the allocator parameter and that's why I think the compiler gives a warning: it's not a perfect match in the signature of the function.
Has anybody tried to do something like this?
Don’t Do That. Use NSMapTable.
if you just want the default CFRetain/CFRelease behaviour, this should work:
void MONDictionaryReleaseCallback(CFAllocatorRef allocator, const void* value) {
#pragma unused(allocator)
assert(value);
if (0 != value) {
CFRelease(value);
}
}
the retain callback should be easy to implement from there.
I managed to get it working using the kCFTypeDictionaryKeyCallBacks constant instead of manually declaring the key callbacks.
The code now looks like this:
id<NSObject> obj = (id)(CFDictionaryCreateMutable(NULL, capacity, &kCFTypeDictionaryKeyCallBacks, &valueCallbacks));
However, i'm still curious why isn't my initial code working
If you don't mind playing with the runtime a bit, this is something I'm working on for a project of mine (it works ATM but it's a bit sloppy). It dynamically creates a new subclass of any object you add and set that object's class to the subclass. The subclass keeps an array of objects that should be notified whenever the object is deallocated. The dictionary adds itself to this array so that it can remove the object if it's ever deallocated.