struct Row
{
Row() { puts("default"); }
Row(const Row &other) { puts("copy"); }
Row(Row &&other) { puts("move"); }
explicit Row(int) { puts("conv. c'tor"); }
};
int main()
{
Row rs;
Row r[3] = {1, 3, rs};
Row r3[3]{1, 3, rs}; // no conversion exists
}
I know explicit constructor is not a candidate for copy initialization. But, How come when direct initializing results in error?
And also How array of objects allocated in memory? Is it same like array of scalar types?
If I turn off elide constructors flag and remove explicit keyword, I get conv, move, conv, move and copy in first and also the same in second? can someone explain that?
C++11 dcl.init#14
The initialization that occurs in the form
T x = a;
as well as in argument passing, function return, throwing an exception ([except.throw]), handling an exception ([except.handle]), and aggregate member initialization ([dcl.init.aggr]) is called copy-initialization.
Aggregate member initialization is copy-initialization, not direct-initialization.
Related
I have not much experience in using lambda's - I was hoping someone could explain what I did below in 'layman's terms' (if possible).
I have a std::vector with a number of objects (or none). Each object has an id. I want to place the object with the id I am interested in at the back of the vector.
I did that like so
std::vector<my_ob> l_obs;
[...] // populate the vector
auto l_elem = std::find_if(l_obs.rbegin(),
l_obs.rend(), [](my_ob const& ob){ return ob.mv_id == 8;});
if(l_elem-l_obs.rbegin())
std::iter_swap(l_elem, l_obs.rbegin());
I am using a reverse iterator as I expect the match to already be at the back of the vector in most cases.
The above worked fine, until I moved it into a method and instead of trying to find '8', I wanted to find a value passed as a const int parameter. The compiler told me that the parameter I used was not captured, and that the lambda had no capture default. So I changed the lambda to
[=](my_ob const& ob){ return ob.mv_id == _arg;}
and this all seems to work now.
Why was this = sign needed?
Lambda expressions produce closure objects, which are function objects (similar to a struct with an overloaded operator()).
In order for closures to use variables in the outer scope, they must know how: either by copying the variable into the closure itself, or by referring to it.
Writing
[=](my_ob const& ob){ return ob.mv_id == _arg;}
is equivalent to
[_arg](my_ob const& ob){ return ob.mv_id == _arg;}
which roughly desugars to
struct LAMBDA
{
int _arg;
LAMBDA(int arg) : _arg{arg} { }
auto operator()(my_ob const& ob) const { return ob.mv_id == _arg; }
};
As you can see, _arg needs to be available in the scope of the generated LAMBDA function object, so it needs to be a data member of the closure.
When you were using a literal, no captures were needed as the generated closure looked like:
struct LAMBDA
{
auto operator()(my_ob const& ob) const { return ob.mv_id == 5; }
};
i have declared a map below using stl and inserted some values in it.
#include<bits/stdc++.h>
int main()
{
map<int,int> m;
m[1]=1;
m[2]=1;
m[3]=1;
m[4]=1;
m[5]=1;
m[6]=1;
for(auto it=m.begin();it!=m.end();)
{
cout<<it->first<<" "<<it->second<<endl;
it=it++;
}
return 0;
}
When i executed the above written code it ended up in an infinite loop. Can someone tell me why it does so?
I am incrementing the value of iterator it and then it gets stored in it which should get incremented next time the loop is executed and eventually it should terminate normally.Am i wrong?
The bad line is it = it++;. It is undefined behavior! Because it is not defined, when it is increased, in your case it is increased before the assingment to itsself again, that the value of it before it is increased is assigned to it again and so it keeps at the first position. The correct line would be it = ++it; or only ++it;/it++;, because it changes itsself.
Edit
That is only undefined with the builtin types, but in here that is defined by the source-code of the map in the stl.
If you try doing something similar with an int, you'll get a warning:
int nums[] = { 1, 2, 3, 4, 5 };
for (int i = 0; i < sizeof nums / sizeof *nums; ) {
cout << nums[i] << '\n';
i = i++;
}
warning: operation on 'i' may be undefined [-Wsequence-point]
However, when you're using a class (std::map::iterator) which has operator overloading, the compiler probably isn't smart enought to detect this.
In other words, what you're doing is a sequence point violation, so the behavior is undefined behavior.
The post-increment operation would behave like this:
iterator operator ++ (int) {
auto copy = *this;
++*this;
return copy;
}
So, what happens to your increment step is that iterator it would get overwritten by the copy of its original value. If the map isn't empty, your loop would remain stuck on the first element.
We have the following lightweight classes:
struct A {};
struct B { A get_a() const { return /* sth */; } };
And let's suppose I have an ordered container of type A, and I want to copy objects from another container of type B to it:
std::copy(b_cont.begin(), b_cont.end(),
std::make_insert_iterator(a_cont, a_cont.end())
);
Of course, it won't work because a_cont and b_cont have different types, and classes A and B don't provide conversion operators. The most obvious solution is to call the function get_a for each B object on the range [b_cont.begin(), b_cont.end()), so, lets write a custom insert iterator:
template<template<class...> class container>
struct ba_insert_iterator : public std::insert_iterator<container<A> >
{
using std::insert_iterator<container<A>>::insert_iterator;
ba_insert_iterator& operator=(B const& o)
{
std::insert_iterator<container<A>>::operator=(o.get_a());
return *this;
}
};
template<template<class...> class container>
ba_insert_iterator<container> make_a_inserter(container<A>& c)
{ return ba_insert_iterator<container>(c, c.end()); }
Just an iterator that receives an object of type B, instead of another one of type A, and a function to create them easily. But when instantiating the template:
std::copy(b_cont.begin(), b_cont.end(), make_a_inserter(a_cont));
It says that it doesn't find the operator= because the second operand is an A object (as expected), but the first operand is an std::insert_iterator<std::set<A> >!!, so the compiler is "casting" the iterator to its clase base, which of course lacks of a method for receiving B objects to insert.
Why does it happen?
You inherited operator* (and operator++ too, for that matter) from insert_iterator.
And those return insert_iterator&, not ba_insert_iterator&.
For obvious reasons, std::copy dereferences the output iterator before assigning to it.
I'm calling unordered_map::emplace() and I am storing the returned value (a pair). I just want to access the inserted value from the pair but for the life of me I cannot figure out the correct configuration of this confusing pair.
My unordered map definition:
std::unordered_map<GUID, shared_ptr<Component>> components;
I've looked at the unordered_map::emplace() documentation; according to this the first element in the pair should be the shared_ptr<Component> but the compiler is just not happy.
In the below code I get the error: Error 2 error C2227: left of '->gUid' must point to class/struct/union/generic type
class Component {
public:
template<typename T, typename... Params>
GUID addComponent(Params... params)
{
auto cmp = Component::create<T>(params...);
auto res = components.emplace(cmp->gUid, cmp);
if (!res.second) {
GUID gUid;
getNullGUID(&gUid);
return gUid;
}
return (*res.first)->gUid; // compiler error here
// *Yes I know I can do: return cmp->gUid;
}
GUID gUid; // initialised in constructor
std::unordered_map<GUID, std::shared_ptr<Component>> components;
};
Any idea how to correctly access the pairs second value?
The first of the pair returned from emplace is an iterator -- which, for unordered_map, acts like a pointer to a pair<key, value>. So to get the value from that pair, you need second:
return res.first->second->gUid;
I have a C extension in which I have a main class (class A for example) created with the classical:
Data_Wrap_Struct
rb_define_alloc_func
rb_define_private_method(mymodule, "initialize" ...)
This A class have an instance method that generate B object. Those B objects can only be generated from A objects and have C data wrapped that depends on the data wrapped in the A instance.
I the A object are collected by the garbage collector before a B object, this could result in a Seg Fault.
How can I tell the GC to not collect a A instance while some of his B objects are still remaining. I guess I have to use rb_gc_mark or something like that. Should I have to mark the A instance each time a B object is created ??
Edit : More specifics Informations
I am trying to write a Clang extension. With clang, you first create a CXIndex, from which you can get a CXTranslationUnit, from which you can get a CXDiagnostic and or a CXCursor and so on. here is a simple illustration:
Clangc::Index#new => Clangc::Index
Clangc::Index#create_translation_unit => Clangc::TranslationUnit
Clangc::TranslationUnit#diagnostic(index) => Clangc::Diagnostic
You can see some code here : https://github.com/cedlemo/ruby-clangc
Edit 2 : A solution
The stuff to build the "b" objects with a reference to the "a" object:
typedef struct B_t {
void * data;
VALUE instance_of_a;
} B_t;
static void
c_b_struct_free(B_t *s)
{
if(s)
{
if(s->data)
a_function_to_free_the_data(s->data);
ruby_xfree(s);
}
}
static void
c_b_mark(void *s)
{
B_t *b =(B_t *)s;
rb_gc_mark(b->an_instance_of_a);
}
VALUE
c_b_struct_alloc( VALUE klass)
{
B_t * ptr;
ptr = (B_t *) ruby_xmalloc(sizeof(B_t));
ptr->data = NULL;
ptr->an_instance_of_a = Qnil;
return Data_Wrap_Struct(klass, c_b_mark, c_b_struct_free, (void *) ptr);
}
The c function that is used to build a "b" object from an "a" object:
VALUE c_A_get_b_object( VALUE self, VALUE arg)
{
VALUE mModule = rb_const_get(rb_cObject, rb_intern("MainModule"));\
VALUE cKlass = rb_const_get(mModule, rb_intern("B"));
VALUE b_instance = rb_class_new_instance(0, NULL, cKlass);
B_t *b;
Data_Get_Struct(b_instance, B_t, b);
/*
transform ruby value arg to C value c_arg
*/
b->data = function_to_fill_the_data(c_arg);
b->instance_of_a = self;
return b_instance;
}
In the Init_mainModule function:
void Init_mainModule(void)
{
VALUE mModule = rb_define_module("MainModule");
/*some code ....*/
VALUE cKlass = rb_define_class_under(mModule, "B", rb_cObject);
rb_define_alloc_func(cKlass, c_b_struct_alloc);
}
Same usage of the rb_gc_mark can be found in mysql2/ext/mysql2/client.c ( rb_mysql_client_mark function) in the project https://github.com/brianmario/mysql2
In the mark function for your B class, you should mark the A Ruby object, telling the garbage collector not to garbage collect it.
The mark function can be specified as the second argument to Data_Wrap_Struct. You might need to modify your design somehow to expose a pointer to the A objects.
Another option is to let the A object be an instance variable of the B object. You should probably do this anyway so that Ruby code can obtain the A object from the B object. Doing this would have the side effect of making the garbage collector not collect the A before the B, but you should not be relying on this side effect because it would be possible for your Ruby code to accidentally mess up the instance variable and then cause a segmentation fault.
Edit: Another option is to use reference counting of the shared C data. Then when the last Ruby object that is using that shared data gets garbage collected, you would delete the shared data. This would involve finding a good, cross-platform, thread-safe way to do reference counting so it might not be trivial.