Getting a copy instead of a reference from std::tuple - c++11

I am storing a collection of std::vectors in a std::tuple. However, when I get an element from the tuple and modify it, I am only modifying a copy of the element returned.
template<typename... Ts>
class ComponentStore
{
public:
ComponentStore()
{
}
~ComponentStore()
{
}
template<typename T>
std::vector<T>& Get()
{
return std::get<std::vector<T>>(m_components);
}
private:
std::tuple<std::vector<Ts>...> m_components;
};
This is how I plan to use the ComponentStore class:
ecs::component::ComponentStore<ecs::component::Position, ecs::component::Velocity> comstore;
//Get the position vector
auto positionvec = comstore.Get<ecs::component::Position>();
//Add a new position
positionvec.emplace_back(ecs::component::Position{});
//Later on, get the position vector again
auto positionvec2 = comstore.Get<ecs::component::Position>();
//But it's empty??? this is wrong. It should have 1 element.

by using auto by itself, you create a variable of the deduced non-reference type, so
auto positionvec = comstore.Get<ecs::component::Position>();
creates a new vector;
you can fix this by using auto&:
auto& positionvec = comstore.Get<ecs::component::Position>();

Related

pop_front() with error "assignment of member in read-only object"

What is this expression unassignable? I am trying to implement a doubly linked list in c++. This is the struct of the Node:
struct NodoLDL
{
T dato;
NodoLDL *anterior;
NodoLDL *siguiente;
NodoLDL(const T &elem, NodoLDL *ant = nullptr, NodoLDL *sig = nullptr):
dato(elem),
anterior(ant),
siguiente(sig)
{}
};
And this is the list class:
template <typename T>
class LDL
{
private:
#include "nodoldl.h"
size_t listSize;
NodoLDL *listFront; //head
NodoLDL *listBack; //tail
public:
LDL() : listSize(0), listFront(nullptr), listBack(nullptr)
{}
void pop_front() const;
(. . .)
}
This is the pop_front function, I get an error on listFront = temp;, what I meant to do with the code is in each following line as comments:
template<typename T>
void LDL<T>::pop_front() const
{
if(empty()){
throw invalid_argument("pop_front() on empty list");
}else{
NodoLDL *temp = listFront->siguiente;
///temp points to the following node in the list (from listFront)
temp->anterior = nullptr;
//Now that temp is at the "second" node in the list,
//the pointer to the node before will be null,
//as the actual listFront will be deleted.
delete listFront;
//It deletes the node
listFront = temp;
//Now listFront is equal to temp, which is at the second node
}
}
Why is that logic wrong? How can I fix it?
The function changes the state of the object on which it is called. It does not make sense to make it a const member function. Change it to a non-const member function.

Change data in std::vector inside const context

It there a way to change the data stored inside a std::vector inside a const function? See the following code to understand what I want to accomplish:
// class holding properties and data
class Output{
public:
int * values; // possibility 1: raw pointer
std::vector<int> vc; // possibility 2: std::vector
mutable std::vector<int> vm; // possibility 3: mutable vector
//std::vector<mutable int> vm; something like this,
};
class Node{
Output out;
void test()const{
// i want to change the "data" of the Output but not the Object
out.values[0] = 0;//works: i can change the output data
out.values = nullptr;//works: compile error, i cant change the pointer
out.vc[0] = 1; // compile error, not possible :(
out.vm[0] = 1; // that is what i want
out.vm.resize(3); // this is now possible, but should be not possible
}
};
I can use a raw pointer to achieve my goal, but i would prefer a std::vector if this is possible.
A mutable content vector may looks like this:
template<typename T>
class mutable_vector : public std::vector<T>{
public:
T& operator[](int index)const{
return const_cast<mutable_vector<T>*>(this)->data()[index];
}
typename std::vector<T>::iterator begin()const{
return const_cast<mutable_vector<T>*>(this)->begin();
}
typename std::vector<T>::iterator rbegin()const{
return const_cast<mutable_vector<T>*>(this)->rbegin();
}
};

How to properly create template object of type T i.e. T result = T();

Hi I am trying to create an object of type T where T is a pointer via the use of T result = T(). But instead of calling the constructor it simply returns a null pointer.
Here is an example of some affected code:
template <class T>
T readBlockchain(std::ifstream* stream) {
T result = T(); // Result is null after this
decltype(result->getLastBlock()) blkPtr = result->getLastBlock();
auto blk = *blkPtr;
decltype(result->getLastBlock()) lastBlock = &readBlock<decltype(blk)>(stream);
if(!lastBlock->verify())
return nullptr;
unsigned long count = *readUnsignedLong(stream);
unsigned long orphanCount = *readUnsignedLong(stream);
std::map<std::string, decltype(blk)> blocks = std::map<std::string, decltype(blk)>();
for(int i = 0; i < count - 1; i++){
decltype(blk) block = readBlock<decltype(blk)>(stream);
if(!block.verify())
return nullptr;
blocks.insert(std::make_pair(block.getHash(), block));
}
std::vector<Blockchain<decltype(blk)>*> orphanedChains = std::vector<Blockchain<decltype(blk)>*>();
for(int i = 0; i < orphanCount - 1; i++){
Blockchain<decltype(blk)>* orphan = &readOrphanedChain<Blockchain<decltype(blk)>>(stream);
orphanedChains.push_back(orphan);
}
result->setLastBlock(lastBlock);
result->setCount(count);
result->setOrphanCount(orphanCount);
result->setBlocks(blocks);
result->setOrphanedChains(orphanedChains);
return result;
}
If my understanding is correct. In order to generalize your readBlockchain correctly, you would want when T is a pointer to create a new object of T in the heap and when T is a concrete type to create a regular T object by calling the constructor of T. One solution would be to use the following specialization construct.
template<typename T>
struct CreateNew {
template<typename... Args>
static T apply(Args&&... args) { return T(std::forward<Args>(args)...); }
};
template<typename T>
struct CreateNew<T*> {
template<typename... Args>
static decltype(auto) apply(Args&&... args) { return std::make_unique<T>(std::forward<Args>(args)...); }
};
That is, you could create a template class that takes a template argument T along with a specialization of that template class for pointers of type T*. Inside the primary template (e.g., static member function apply) you'll create objects of type T by calling the constructor of class T and inside the specialization you'll create heap objects of T* (Notice that in the specialization I return a std::unique_ptr<T*> for convenience).
Thus, your readBlockChain template function would become:
template <class T>
decltype(auto) readBlockchain(std::ifstream* stream) {
auto result = CreateNew<T>::apply(/* T constructor arguments */);
...
return result;
}
Live Demo

Converting one parameter pack into another?

I would like to convert a parameter pack of iterator types into the corresponding parameter pack of references. This is what I've got so far:
template <class Iterator, class... Iterators>
class cast_iterators_to_references
{
using head_reference_type = std::iterator_traits<Iterator>::reference
// TODO
//using type = ;
};
Where do I take it from here?
The reason I'm doing this is to create a "view" object. It contains a tuple of iterators to the containers it's referencing. I'd like to have a method that returns a tuple of the elements at some index so that I can create a custom iterator for it, create begin and end methods, and use it in a range-based for statement.
Here's how it could be used:
template<class Iterators...>
tuple_iterator
{
public:
using tuple_type = std::tuple<Iterators...>;
using references = cast_iterators_to_references<Iterators...>;
using tuple_element_type = std::tuple<references>;
// ... construct from tuple, copy/move constructors, copy/move assignment etc.
tuple_element_type operator[](size_t index)
{
tuple_element_type element;
for (size_t i = 0; i < sizeof...(Iterators); i++)
std::get<i>(element) = std::get<i>(data_)[offset_ + index];
return element;
}
// ... increment, decrement operators etc.
private:
tuple_type data_;
size_t offset_;
}
Parameter packs are not first-class, so they are a bit fiddly to handle.
A first stab at the cast_iterators_to_references metafunction could be this :
// Not defined, used to wrap a pack into a type
template <class...> struct pack;
template <class... Iterators>
using cast_iterators_to_references = pack<
typename std::iterator_traits<Iterators>::reference...
>;
But then you need helper classes to unpack the pack via pattern-matching :
template <class> unpack_to_tuple;
template <class... Ts> unpack_to_tuple<pack<Ts...>> {
using type = std::tuple<Ts...>;
};
// In your class
using references = cast_iterators_to_references<Iterators...>;
using tuple_element_type = typename unpack_to_tuple<references>::type;
So you're probably better off using the parameter pack directly :
using tuple_element_type = std::tuple<
typename std::iterator_traits<Iterators>::reference...
>;
Your operator[] can be written as follows :
template <std::size_t... Idx>
auto access(size_t index, std::index_sequence<Idx...>) {
return std::tie(std::get<Idx>(data_)[index + offset_]...);
}
tuple_element_type operator[](size_t index)
{
return access(index, std::index_sequence_for<Iterators...>{});
}

Persistent expression templates with unique_ptr and matrices

I want to use expression templates to create a tree of objects that persists across statement. Building the tree initially involves some computations with the Eigen linear algebra library. The persistent expression template will have additional methods to compute other quantities by traversing the tree in different ways (but I'm not there yet).
To avoid problems with temporaries going out of scope, subexpression objects are managed through std::unique_ptr. As the expression tree is built, the pointers should be propagated upwards so that holding the pointer for the root object ensures all objects are kept alive. The situation is complicated by the fact that Eigen creates expression templates holding references to temporaries that go out of scope at the end of the statement, so all Eigen expressions must be evaluated while the tree is being constructed.
Below is a scaled-down implementation that seems to work when the val type is an object holding an integer, but with the Matrix type it crashes while constructing the output_xpr object. The reason for the crash seems to be that Eigen's matrix product expression template (Eigen::GeneralProduct) gets corrupted before it is used. However, none of the destructors either of my own expression objects or of GeneralProduct seems to get called before the crash happens, and valgrind doesn't detect any invalid memory accesses.
Any help will be much appreciated! I'd also appreciate comments on my use of move constructors together with static inheritance, maybe the problem is there somewhere.
#include <iostream>
#include <memory>
#include <Eigen/Core>
typedef Eigen::MatrixXi val;
// expression_ptr and derived_ptr: contain unique pointers
// to the actual expression objects
template<class Derived>
struct expression_ptr {
Derived &&transfer_cast() && {
return std::move(static_cast<Derived &&>(*this));
}
};
template<class A>
struct derived_ptr : public expression_ptr<derived_ptr<A>> {
derived_ptr(std::unique_ptr<A> &&p) : ptr_(std::move(p)) {}
derived_ptr(derived_ptr<A> &&o) : ptr_(std::move(o.ptr_)) {}
auto operator()() const {
return (*ptr_)();
}
private:
std::unique_ptr<A> ptr_;
};
// value_xpr, product_xpr and output_xpr: expression templates
// doing the actual work
template<class A>
struct value_xpr {
value_xpr(const A &v) : value_(v) {}
const A &operator()() const {
return value_;
}
private:
const A &value_;
};
template<class A,class B>
struct product_xpr {
product_xpr(expression_ptr<derived_ptr<A>> &&a, expression_ptr<derived_ptr<B>> &&b) :
a_(std::move(a).transfer_cast()), b_(std::move(b).transfer_cast()) {
}
auto operator()() const {
return a_() * b_();
}
private:
derived_ptr<A> a_;
derived_ptr<B> b_;
};
// Top-level expression with a matrix to hold the completely
// evaluated output of the Eigen calculations
template<class A>
struct output_xpr {
output_xpr(expression_ptr<derived_ptr<A>> &&a) :
a_(std::move(a).transfer_cast()), result_(a_()) {}
const val &operator()() const {
return result_;
}
private:
derived_ptr<A> a_;
val result_;
};
// helper functions to create the expressions
template<class A>
derived_ptr<value_xpr<A>> input(const A &a) {
return derived_ptr<value_xpr<A>>(std::make_unique<value_xpr<A>>(a));
}
template<class A,class B>
derived_ptr<product_xpr<A,B>> operator*(expression_ptr<derived_ptr<A>> &&a, expression_ptr<derived_ptr<B>> &&b) {
return derived_ptr<product_xpr<A,B>>(std::make_unique<product_xpr<A,B>>(std::move(a).transfer_cast(), std::move(b).transfer_cast()));
}
template<class A>
derived_ptr<output_xpr<A>> eval(expression_ptr<derived_ptr<A>> &&a) {
return derived_ptr<output_xpr<A>>(std::make_unique<output_xpr<A>>(std::move(a).transfer_cast()));
}
int main() {
Eigen::MatrixXi mat(2, 2);
mat << 1, 1, 0, 1;
val one(mat), two(mat);
auto xpr = eval(input(one) * input(two));
std::cout << xpr() << std::endl;
return 0;
}
Your problem appears to be that you are using someone else's expression templates, and storing the result in an auto.
(This happens in product_xpr<A>::operator(), where you call *, which if I read it right, is an Eigen multiplication that uses expression templates).
Expression templates are often designed to presume the entire expression will occur on a single line, and it will end with a sink type (like a matrix) that causes the expression template to be evaluated.
In your case, you have a*b expression template, which is then used to construct an expression template return value, which you later evaluate. The lifetime of temporaries passed to * in a*b are going to be over by the time you reach the sink type (matrix), which violates what the expression templates expect.
I am struggling to come up with a solution to ensure that all temporary objects have their lifetime extended. One thought I had was some kind of continuation passing style, where instead of calling:
Matrix m = (a*b);
you do
auto x = { do (a*b) pass that to (cast to matrix) }
replace
auto operator()() const {
return a_() * b_();
}
with
template<class F>
auto operator()(F&& f) const {
return std::forward<F>(f)(a_() * b_());
}
where the "next step' is passed to each sub-expression. This gets trickier with binary expressions, in that you have to ensure that the evaluation of the first expression calls code that causes the second sub expression to be evaluated, and then the two expressions are combined, all in the same long recursive call stack.
I am not proficient enough in continuation passing style to untangle this knot completely, but it is somewhat popular in the functional programming world.
Another approach would be to flatten your tree into a tuple of optionals, then construct each optional in the tree using a fancy operator(), and manually hook up the arguments that way. Basically do manual memory management of the intermediate values. This will work if the Eigen expression templates are either move-aware or do not have any self-pointers, so that moving at the point of construction doesn't break things. Writing that would be challenging.
Continuation passing style, suggested by Yakk, solves the problem and isn't too insane (not more insane than template metaprogramming in general anyhow). The double lambda evaluation for the arguments of binary expressions can be tucked away in a helper function, see binary_cont in the code below. For reference, and since it's not entirely trivial, I'm posting the fixed code here.
If somebody understands why I had to put a const qualifier on the F type in binary_cont, please let me know.
#include <iostream>
#include <memory>
#include <Eigen/Core>
typedef Eigen::MatrixXi val;
// expression_ptr and derived_ptr: contain unique pointers
// to the actual expression objects
template<class Derived>
struct expression_ptr {
Derived &&transfer_cast() && {
return std::move(static_cast<Derived &&>(*this));
}
};
template<class A>
struct derived_ptr : public expression_ptr<derived_ptr<A>> {
derived_ptr(std::unique_ptr<A> &&p) : ptr_(std::move(p)) {}
derived_ptr(derived_ptr<A> &&o) = default;
auto operator()() const {
return (*ptr_)();
}
template<class F>
auto operator()(F &&f) const {
return (*ptr_)(std::forward<F>(f));
}
private:
std::unique_ptr<A> ptr_;
};
template<class A,class B,class F>
auto binary_cont(const derived_ptr<A> &a_, const derived_ptr<B> &b_, const F &&f) {
return a_([&b_, f = std::forward<const F>(f)] (auto &&a) {
return b_([a = std::forward<decltype(a)>(a), f = std::forward<const F>(f)] (auto &&b) {
return std::forward<const F>(f)(std::forward<decltype(a)>(a), std::forward<decltype(b)>(b));
});
});
}
// value_xpr, product_xpr and output_xpr: expression templates
// doing the actual work
template<class A>
struct value_xpr {
value_xpr(const A &v) : value_(v) {}
template<class F>
auto operator()(F &&f) const {
return std::forward<F>(f)(value_);
}
private:
const A &value_;
};
template<class A,class B>
struct product_xpr {
product_xpr(expression_ptr<derived_ptr<A>> &&a, expression_ptr<derived_ptr<B>> &&b) :
a_(std::move(a).transfer_cast()), b_(std::move(b).transfer_cast()) {
}
template<class F>
auto operator()(F &&f) const {
return binary_cont(a_, b_,
[f = std::forward<F>(f)] (auto &&a, auto &&b) {
return f(std::forward<decltype(a)>(a) * std::forward<decltype(b)>(b));
});
}
private:
derived_ptr<A> a_;
derived_ptr<B> b_;
};
template<class A>
struct output_xpr {
output_xpr(expression_ptr<derived_ptr<A>> &&a) :
a_(std::move(a).transfer_cast()) {
a_([this] (auto &&x) { this->result_ = x; });
}
const val &operator()() const {
return result_;
}
private:
derived_ptr<A> a_;
val result_;
};
// helper functions to create the expressions
template<class A>
derived_ptr<value_xpr<A>> input(const A &a) {
return derived_ptr<value_xpr<A>>(std::make_unique<value_xpr<A>>(a));
}
template<class A,class B>
derived_ptr<product_xpr<A,B>> operator*(expression_ptr<derived_ptr<A>> &&a, expression_ptr<derived_ptr<B>> &&b) {
return derived_ptr<product_xpr<A,B>>(std::make_unique<product_xpr<A,B>>(std::move(a).transfer_cast(), std::move(b).transfer_cast()));
}
template<class A>
derived_ptr<output_xpr<A>> eval(expression_ptr<derived_ptr<A>> &&a) {
return derived_ptr<output_xpr<A>>(std::make_unique<output_xpr<A>>(std::move(a).transfer_cast()));
}
int main() {
Eigen::MatrixXi mat(2, 2);
mat << 1, 1, 0, 1;
val one(mat), two(mat), three(mat);
auto xpr = eval(input(one) * input(two) * input(one) * input(two));
std::cout << xpr() << std::endl;
return 0;
}

Resources