Using a prvalue to create a shared_pointer - c++

I have a class functionCombiner which constructor looks like this
FunctionCombiner::FunctionCombiner(std::vector<std::shared_ptr<valuationFunction>> Inner_) : Inner(std::move(Inner_)), valuationFunction("", 0) //<- Needs to initalize itself even though it gets all data from inner functions.
{
}
In my main class I'm calling it like this:
vector<std::shared_ptr<valuationFunction>> combinedStillFrontFunctions{ stillFrontStock, stillFrontEuropeanCall };
std::shared_ptr<valuationFunction> StillFrontFunctions = std::make_shared<FunctionCombiner>(combinedStillFrontFunctions);
What I would like to be able to do is reduce that to one line by constructing it in place like so
std::shared_ptr<valuationFunction> StillFrontFunctions = std::make_shared<FunctionCombiner>({ stillFrontStock, stillFrontEuropeanCall });
Which the compiler doesn't like. Is there a way to make this work? This works obviously:
FunctionCombiner StillFrontFunctions({ stillFrontStock, stillFrontEuropeanCall });
But I need it to be a shared pointer.

(Shorting some names to make the example readable w/o horizontal scrollbars. You should consider doing the same...)
Passing {x,y} to make_shared() is attempting to forward a brace-enclosed initializer list, not to initialize the value in the shared pointer, but the temporary object its constructor takes. It's not something that can be forwarded since it's not a full expression on its own. So make a temporary vector with those values:
... = make_shared<FunComb>(vector<shared_ptr<valFun>>{FS, FEC});
Another approach may be to change FunComb's constructor to be a (or add a new) variadic constructor, removing the need to pass in a vector just to hold the inputs.

Related

How to lazy initialize a map using std::optional, and add to it using emplace

I have a class with a std::optional map, the reasoning here is that a map is expensive to construct so I'm looking for ways to minimize the impact. As the map is not always used, the thinking is why construct it until it IS used.
I'm having trouble with adding values to the class after construction, the syntax eludes me :), or perhaps I misunderstood some limitation and it can't actually be used this way. Some insight would be appreciated.
class A {
public:
void addValues() {
_map_value.emplace(/* what goes here ?*/);
// It is expecting something like std::enable_if_t<std::is_constructible<std::map< .... initializer list
}
private:
std::optional<std::map<std::string, ResourceValue>> _map_value{};
};
I've tried making pair's and various forms of emplace. I see i'm supposed to use std::optional::emplace, but I think this is just for construction, not for accessing and adding to the map afterwards. How can I manage this map after its been optionally constructed?
std::optional<T>::emplace takes a number of arguments and invokes the constructor of T with those arguments to construct the managed value in place. In this case it doesn't take any parameters, because you wouldn't pass any parameters to the constructor of map.
Maybe check beforehand if the optional is already initialized or not and then access the managed object with ->:
if(!_map_value) { // if the optional is empty
_map_value.emplace(); // construct
_map_value->insert(...); // Do stuff with the map
}

Constructing an object to return by value elsewhere

In a wrapper to interface the V8 JavaScript engine with C++ code, I'd like to call a C++ function passing it an object by value. The object is automatically constructed from data inside JavaScript.
The C++ function to call takes an object of type T and a template is used to generate an adapter function A, returning T by value. The problem is that the adapter function A needs to call a JavaScript function passing it another C++ function B as a callback. The object of type T is constructed in that function B. It cannot be returned back to A through JavaScript, which doesn't know how to handle the object of type T.
The simplest way is to have a local variable of type T inside function A. A pointer to it is given to B, which assigns a new value to the local variable, which A later returns, approximately like so (Some details omitted regarding how arguments are passed to callJavaScript and callback. In reality, T's constructor and thus the B function may take any number of more complicated types as parameters):
C++ code:
T A() {
T data;
callJavaScript("someJavaScriptFunction", &B, &data);
return data;
}
void B(T *data, int importantValue) {
*data = T(importantValue);
}
JavaScript code:
function someJavaScriptFunction(callback, dataRef) {
callback(dataRef, getImportantValueSomehow());
}
But what if the type T doesn't support assignment or even have a copy constructor? Is there a way to avoid unnecessary copying? I thought of allocating empty space inside function A as a local variable:
typename std::aligned_storage<sizeof(T), alignof(T)>::type data;
Function B could then construct the object in that space using placement new, but how can I return the resulting object from A using move semantics? How to call a possible destructor correctly?
My final idea was to use more template trickery to allocate space for parameters for type T's constructor inside function A, set them through pointers from B and finally construct the object inside A, but it will get nasty if data in some parameters goes out of scope when callJavaScript returns. Is there a solution for that?
EDIT: The point of all this is to get the contents of a JavaScript object into C++. Reading the object's properties from C++ requires looking them up by name using strings. A JIT-compiled function in V8 has more direct access to the object's fields and reads of the object's properties in someJavaScriptFunction get compiled into simple pointer reads. Then it can call the C++ callback with various parameters which are reasonably fast to convert from JavaScript value handles into C++ types.
EDIT2: The simple first idea is:
typename std::aligned_storage<sizeof(T), alignof(T)>::type data;
::new(&data) T(); // THIS LINE ACTUALLY PLACED IN ANOTHER FUNCTION
return(*reinterpret_cast<T *>(&data));
But should I call the destructor for the object T constructed in data, and when to call it, and how? This is a library and adding code to the recipient of the return value is not really an option.
I am not sure I understood completely your question, but it seems that you don't have a need to pass output parameters in your functions.
Simply have function A return a value as you already put in the question, and have B return a value.
Because of the "named return value optimization" there is no need for assignment operator nor copy constructors. That is, if your code satisfies the requirements for "NRVO" you would be fine:
T B(int importantValue) { return T{importantValue}; }
Does not need assignment operator nor copy constructor from T.
Then, change callJavascript to not require output parameters, but return a value, and then this will work without copy constructors or assignment operator:
T A() { A rv{callJavascript(&B)}; return rv; }
In general, make it so that your functions don't require output parameters, otherwise you require your types to have copy constructors and assignment operators, or to violate the type system.
By the way, make callJavascript such that it is a template that takes a callable as argument.
I ended up using a wrapper around A that handles calling placement new and A's destructor. It allows the library's user to supply any class A, as long as it has a move constructor. The full code of a working test and discussion about it are found in a newer, better formulated question Placement new, return by value and safely dispose temporary copies and its accepted answer.

Construct returned object in calling function's scope

Is it possible to force C++ to construct an object in the scope of a calling function? What I mean is to explicitly do what an return value optimization (RVO) does.
I have some container classes which are in a chain of derivation. Since the classes are constructed with stack data, they can't be returned, so I disabled the copy constructor and assignment operators. For each class, I am providing an iterator. The constructor of each iterator has only one argument: a pointer to the container class. To get the iterator, I want to use this function:
BindPackIterator BindPack.begin(void)
{
return BindPackIterator(this);
}
in this context:
for (auto i=bindpack.begin(); !i.end(); ++i) { i.run(); }
The compiler issues errors, complaining about not being able to copy the BindPackIterator object. Remember, I disabled them.
What I want to happen is for the BindPackIterator to be instantiated in the calling function's scope to avoid either a copy or move operation.
In this particular case, I know I can do a workaround, changing the begin function to return a BindPack pointer,
for(BindPackIterator i=bindpack.begin(); !i.end(); ++i) { i.run(); }
and I've experimented a bit, without success, with decltype and this construction:
auto BindPack::begin(void) -> BindPackIterator
{
return BindPackIterator(this);
}
This is just the example with which I'm currently frustrated. There have been other projects where the obvious solution is for the function to instantiate an object in the calling function's scope. The move constructor (foo&&) helps in some cases, but for objects with many data members, even that can be inefficient. Is there a design pattern that allows object construction/instantiation in the caller's scope?
Putting n.m.'s comment into code, write a constructor for BindPackIterator that takes a BindPack and initializes the iterator in the "begin" state. e.g:
BindPackIterator(BindPack* pack) : pack(pack), pos(0){ }
That you can use in your for loop:
BindPack pack;
for(BindPackIterator i(&pack); !i.end(); ++i){
i.run();
}
Live demo
Is it fair to say that the answer is "No," it is not possible to construct a returned object in the calling function's scope? Or in other words, you can't explicitly tell the compiler to use RVO.
To be sure, it is a dangerous possibility: stack memory used to construct the object while available in the called function will not be valid in the calling function, even though the values might remain untouched in the abandoned stack frame. This would result in unpredictable behavior.
Upon further consideration, while summing up at the end of this response, I realized that the compiler may not be able to accurately predict the necessary stack size for objects created in the calling function and initialized in a called function, and it would not be possible to dynamically expand the stack frame if the execution had passed to another function. These considerations make my whole idea impossible.
That said, I want to address the workarounds that solve my iterator example.
I had to abandon the idea of using auto like this:
for (auto i=bindpack.begin(); !i.end(); ++i)
Having abandoned auto, and realizing that it's more sensible to explicitly name the variable anyway (if the iterator is different enough to require a new class, it's better to name it to avoid confusion) , I am using this constructor:
BindPackIterator(BindPack &ref) : m_ref_pack(ref), m_index(0) { }
in order to be able to write:
for (BindPackIterator i=bindpack; !i.end(); ++i)
preferring to initialize with an assignment. I used to do this when I was last heavily using C++ in the late 1990's, but it's not been working for me recently. The compiler would ask for a copy operator I didn't want to define for reasons stated above. Now I think that problem was due to my collection of constructors and assignment operators I define to pass the -Weffc++ test. Using simplified classes for this example allowed it to work.
Another workaround for an object more complicated than an iterator might be to use a tuple for the constructor argument for objects that need multiple variables to initialize. There could be a casting operator that returns the necessary tuple from the class that initializes the object.
The constructor could look like:
FancyObject(BigHairyTuple val) : m_data1(get<0>(val)), m_data2(get<1>(val), etc
and the contributing object would define this:
class Foo
{
...
operator BigHairyTuple(void) {
return BigHairyTuple(val1, val2, ...);
}
};
to allow:
FancyObject fo = foo;
I haven't tested this specific example, but I'm working with something similar and it seems likely to work, with some possible minor refinements.

C++ inserting object with constructor into map

I was trying to methods to insert into a map, inserting a pair into a map works fine, the code looks like this:
type insert(){
map<int,MyClass> myMap;
MyClass myObj(parameter);
myMap.insert(pair<int,MyClass>(0,myObj));
...
return myMap;
}
However, I decide to use the other way, basically:
map[key] = value;
And, it look like this:
type insert(){
map<int,MyClass> myMap;
MyClass myObj(parameter);
myMap[i] = myObj;
....
return myMap;
}
compiler will give an error saying: "no matching function for call to myObj::myObj(), candidates are: " and it gives my self defined constructor.
My guess is that when using the indexing way to cast to a map, if I were to pass in an object, then it will automatically call its default constructor with no parameter. But since I have already got a self defined constructor with parameter, it will therefore give an error. Therefore, I tried creating a map in which the value is an object, and the object has only default constructor. This way, compiler is not complaining.
My problem is I don't find any document confirming my idea. If it is right, why does the map with value of object made to call the default constructor rather than existing constructor?
The problem is that std::map::operator[] will actually return a reference to the object on the given index and if there is non, default construct one. Your assignment takes place after acquiring a reference.
Use std::map::emplace to directly construct an object in place:
myMap.emplace(i, parameter);
What happens when you call
myMap[i] = myObj;
is that, if there is no element with key i, one is inserted with a value initialized (which for a user defined type means default constructed) mapped type. You then assign to it the value on the RHS of the assignment. The first part requires that the type be default constructable.
std::map requires your type must have a no-argument constructor. See here for a discussion of why.

Accessing a Class Function when the Class instance is within a Struct

I have an array of structs -
struct MagicalUnicornBullets {
PS2Sprite SparklyUnicornBullet();
bool onscreen;
};
MagicalUnicornBullets MagicalUnicornBullets[25];
I want to loop through the array, and initialise the contents of the struct.
Obviously, this is just the case of a for loop, and for the bool it's simply onscreen = false; but how would I initialise the SparklyUnicornBullet?
Right now my code is -
MagicalUnicornBullets[i].SparklyUnicornBullet.ScaleAbsolute(4,4);
I'm well aware this is wrong - but how do I access the class functions when they're within the Struct?
Realize that SparklyUnicornBullet is actually a member function which returns a PS2Sprite object. This returned PS2Sprite has a member function ScaleAbsolute which you want to call. So your code above is nearly correct. You are simply missing ()'s:
MagicalUnicornBullets[i].SparklyUnicornBullet().ScaleAbsolute(4,4);
That said, there's a number of things that's bad with your code. For one, you are declaring an array that has the same name as an object:
MagicalUnicornBullets MagicalUnicornBullets[25];
I think this is allowed, but it is so evil and malmotivated that I can't even say that for certian, because I would reject any such code regardless of it's motivation or legality. You should give the array a different name:
MagicalUnicornBullets bullets[25];
Next, your initialization loop is unneeded. The code:
MagicalUnicornBullets MagicalUnicornBullets[25];
creates a C-style array of 25 MagicalUnicornBullets by calling each one's default constructor. So the easiest thing to do is to simply provide a default constructor that does what you want:
struct MagicalUnicornBullets {
MagicalUnicornBullets();
// ...
};
MagicalUnicornBullets::MagicalUnicornBullets()
: onscreen(false)
{
SparklyUnicornBullet().ScaleAbsolute(4,4)
}
Now there's no need for a loop at all. All 25 will be constructed and initialized the way you want.
Finally, usually in C++ it's advantagerous to not use a C-style array at all, but a collection class such as std::vector.