Can you use a C++11 ranged-based for loop with an std::weak_ptr instead of using a for_each with lambda, as seen below?
std::vector<std::weak_ptr<IObservable>> observers;
std::for_each(this->observers.cbegin(), this->observers.cend(),
[](const std::weak_ptr<IObservable>& _o)
{
auto observer = _o.lock();
if (observer)
{
observer->Notify()
}
});
I don't see why not. Are you getting any error messages?
this:
for( const auto& o: observers ) {
if( auto observer = o.lock() ) {
observer->Notify();
}
}
should work ok... :D
Considering that std::for_each most likely translates to:
template<class InputIt, class UnaryFunction>
UnaryFunction for_each(InputIt first, InputIt last, UnaryFunction f)
{
for (; first != last; ++first) {
f(*first);
}
return f;
}
and that range-based for loops translates to:
{
auto && __range = range_expression ;
for (auto __begin = begin_expr,
__end = end_expr;
__begin != __end; ++__begin) {
range_declaration = *__begin;
loop_statement
}
}
You can see just few differences:
the latter does not allow iterators different from begin() and end()
the former returns the unary function
But in the overall picture, using it in place of your std::for_each, in you situation, would work perfectly fine.
And here's how:
std::vector<std::weak_ptr<IObservable>> observers;
for (const auto& _o) {
auto observer = _o.lock();
if (observer)
observer->Notify();
}
Related
I am implementing some sort of nested flat for_each (contrived example):
template <class InputIt, class UnaryFunction>
UnaryFunction flat_nested_for_each_of_sorts(InputIt first, InputIt last, UnaryFunction f) {
while (first != last) {
f = std::for_each(begin(*first), end(*first), std::move(f));
}
return f;
}
I want to return f, as it may be a struct with some data. But I want this function to work with lambdas as well. For example,
int example1() {
int acc = 0;
std::vector<std::vector<int>> values{{1,2},{3,4}};
auto l = [&acc](int i) {acc += i;};
l = flat_nested_for_each_of_sorts(begin(values), end(values), std::move(l));
return acc;
}
Problem is, compiler don't like this code:
error: use of deleted function 'example1()::<lambda(int)>& example1()::<lambda(int)>::operator=(const example1()::<lambda(int)>&)'
I know that in this case copy assignment operator of lambda with captures is deleted. What I don't understand is why not call move assignment operator? If we are to write lambda "by hand", everything works fine:
struct Lambda_sustitution {
int* acc;
Lambda_sustitution() = default;
Lambda_sustitution(int& acc) : acc{&acc} {}
Lambda_sustitution(const Lambda_sustitution&) = delete;
Lambda_sustitution& operator=(const Lambda_sustitution&) = delete;
Lambda_sustitution(Lambda_sustitution&& s) {
acc = s.acc;
s.acc = nullptr;
}
Lambda_sustitution& operator=(Lambda_sustitution&& s) {
acc = s.acc;
s.acc = nullptr;
return *this;
}
void operator()(int i) {*acc += i; };
};
int example2() {
int acc = 0;
std::vector<std::vector<int>> values{{1,2},{3,4}};
Lambda_sustitution l{acc};
l = flat_nested_for_each_of_sorts(begin(values), end(values), std::move(l));
return *l.acc;
}
Compiler Explorer link: https://godbolt.org/z/6Tb5WYqxj
What I don't understand is why not call move assignment operator?
Because lambda doesn't have a move assignment operator either (and it does have a copy constructor).
In fact, you don't need to do any reassignments, you can simply do:
template <class InputIt, class UnaryFunction>
UnaryFunction flat_nested_for_each_of_sorts(InputIt first, InputIt last, UnaryFunction f) {
while (first != last) {
std::for_each(begin(*first), end(*first), f);
++first;
}
return f;
}
And call it like:
int example1() {
int acc = 0;
std::vector<std::vector<int>> values{{1,2},{3,4}};
auto l = [&acc](int i) {acc += i;};
flat_nested_for_each_of_sorts(begin(values), end(values), l);
return acc;
}
Demo
I recently came across this article; which provides a basic implementation of boost's indirect_iterator but for unique_ptr iterators. I decided to tweak the example in the article a little, so that I could use it for vectors outside class members:
template <typename T>
using SPN = std::unique_ptr<Node<T>>;
template <class BaseIterator>
struct DReferenceIterator : BaseIterator
{
explicit DReferenceIterator(const BaseIterator & other) : BaseIterator(other) {}
auto & operator*() const { return *(this->BaseIterator::operator*()); }
auto * operator->() const { return this->BaseIterator::operator*().get(); }
auto & operator[](size_t n) const { return *(this->BaseIterator::operator[](n)); }
};
template<typename T>
auto begin_t(std::vector<SPN<T>> & v)
{
return DReferenceIterator<typename std::vector<SPN<T>>::iterator>(v.begin());
}
template<typename T>
auto end_t(std::vector<SPN<T>> & v)
{
return DReferenceIterator<typename std::vector<SPN<T>>::iterator>(v.end());
}
I can use std::find(begin_t(v), end_t(v), value) with no problems at all. However, if I try to call std::sort(begin_t(v), end_t(v)) it does not work at all. I did provide an implemention of operator<() in the Node<T> class, but for some reason my code does not compile. The compile error that I get is very extensive and hard to read, however, I managed to extract something that I think is causing the problem:
binary =: no operator found which takes a right-hand operand of type std::unique_ptr<Node<float>,std::default_delete<_Ty>> (or there is no acceptable conversion)
Does this message mean that std::sort() is trying to copy unique_ptr? In which case, does this mean that the DReferenceIterator wrapper does not work as intended? I'm fairly new to C++, so if this is not the case, please help me understand what exactly the problem is.
Your DReferenceIterator is lying to the standard library as to what it is exposing. This is causing the errors you see trying to std::sort through it.
By deriving from BaseIterator, you are inheriting the following (among others) BaseIterator::value_type, BaseIterator::pointer and BaseIterator::reference, which don't match the return types of your operators.
A correct implementation would be more like
template <class BaseIterator>
struct DReferenceIterator
{
using value_type = BaseIterator::value_type::element_type;
using reference = value_type &;
using pointer = value_type *;
using difference_type = BaseIterator::difference_type
using iterator_category = BaseIterator::iterator_category;
explicit DReferenceIterator(const BaseIterator & other) : other(other) {}
reference operator*() const { return **other; }
pointer operator->() const { return (*other).get(); }
reference operator[](size_t n) const { return (*other)[n]; }
DReferenceIterator& operator++() { ++other; return *this; }
DReferenceIterator& operator--() { --other; return *this; }
DReferenceIterator& operator+=(difference_type n) { other += n; return *this; }
DReferenceIterator& operator-=(difference_type n) { other -= n; return *this; }
difference_type operator-(DReferenceIterator& rhs) { return other - rhs.other; }
bool operator<(DReferenceIterator& rhs) { return other < rhs.other; }
// And all the other operators, in terms of those
private:
BaseIterator other;
};
I have a small lambda function which shall find and return a QTreeWidgetItem. But if it does not find the given item, then it shall return a nullptr. But if I try to compile it then it gives me an error.
The function:
auto takeTopLevelItem = []( QTreeWidget* aTreeWidget, const QString& aText )
{
const int count = aTreeWidget->topLevelItemCount();
for ( int index = 0; index < count; ++index )
{
auto item = aTreeWidget->topLevelItem( index );
if ( item->text( 0 ) == aText )
{
return aTreeWidget->takeTopLevelItem( index );
}
}
return nullptr; // This causes a compilation error.
};
The error:
Error 1 error C3487: 'nullptr': all return expressions in a lambda must have the same type: previously it was 'QTreeWidgetItem *' cpp 251
I changed the mentioned line with this and now it compiles:
return (QTreeWidgetItem*)( nullptr );
but I would like to avoid this syntax. How can I solve this ?
I use Visual Studio 2012.
You can add an explicit return type annotation:
auto takeTopLevelItem = []( ... ) -> QTreeWidgetItem*
{
// ...
}
That way nullptr will be converted to your pointer type properly. You're getting that error because the lambda assumes no conversions should be made, and treats nullptr_t as a legitimate alternative return type.
As a side note, consider using (std::)optional instead. The nullability of pointers can be used to represent a missing return, but it doesn't mean it necessarily should be.
If you just want to avoid the syntax, rather than the casting, you could it like this:
static_cast<QTreeWidgetItem*>(nullptr);
I made a small example, on how Bartek's and mine's answer really work:
#include <iostream>
class A {
int a;
};
auto bla = [] (A* obj, bool flag) -> A* {
if(flag)
return obj;
return nullptr;
// return static_cast<A*>(nullptr);
};
int main() {
A obj;
A* ptr = &obj;
bool flag = false;
if( bla(ptr, flag) == nullptr)
std::cout << "ok\n";
return 0;
}
I had this very same issue with some Smart Pointers, so I found I could do this to avoid the issue:
auto myFunc= [](MyClass* class)
{
MyPointer* pointer = nullptr;
if( class && class->isValid() )
{
pointer = class->getPointerInstance()
}
return pointer;
}
Similarly, for shared pointer, just repleace MyPointer* by std::shared_ptr<MyPointer>.
So your code would looks like:
auto takeTopLevelItem = []( QTreeWidget* aTreeWidget, const QString& aText )
{
QTreeWidgetItem* item = nullptr;
const int count = aTreeWidget->topLevelItemCount();
for ( int index = 0; index < count; ++index )
{
auto item = aTreeWidget->topLevelItem( index );
if ( item->text( 0 ) == aText )
{
item = aTreeWidget->takeTopLevelItem( index );
break;
}
}
return item;
};
If I have two classes D1 and D2 that both derive from class Base, and I want to construct a particular one based on say, a boolean variable, there are various well known techniques, eg use a factory, or use smart pointers.
For example,
std::unique_ptr<Base> b;
if (flag)
{
b.reset(new D1());
}
else
{
b.reset(new D2());
}
But this uses the heap for allocation, which is normally fine but I can think of times where it would be good to avoid the performance hit of a memory allocation.
I tried:
Base b = flag ? D1() : D2(); // doesn’t compile
Base& b = flag ? D1() : D2(); // doesn’t compile
Base&& b = flag ? D1() : D2(); // doesn’t compile
Base&& b = flag ? std::move(D1()) : std::move(D2()); // doesn’t compile
My intention is that D1 or D2 whichever is chosen is constructed on the stack, and its lifetime ends when b goes out of scope. Intuitively, I feel there should be a way to do it.
I played with lambda functions and found that this works:
Base&& b = [j]()->Base&&{
switch (j)
{
case 0:
return std::move(D1());
default:
return std::move(D2());
}
}();
Why it doesn’t suffer from the same issues as the others that do not compile I do not know.
Further, it would only be suitable for classes that are inexpensive to copy, because despite my explicit request to use move, it does I think still call a copy constructor. But if I take away the std::move, I get a warning!
I feel this is closer to what i think should be possible but it still has some issues:
the lambda syntax is not friendly to old-timers who havent yet
embraced the new features of the language ( myself included)
the copy constructor call as mentioned
Is there a better way of doing this?
If you know all the types, you can use a Boost.Variant, as in:
class Manager
{
using variant_type = boost::variant<Derived1, Derived2>;
struct NameVisitor : boost::static_visitor<const char*>
{
template<typename T>
result_type operator()(T& t) const { return t.name(); }
};
public:
template<typename T>
explicit Manager(T t) : v_(std::move(t)) {}
template<typename T>
Manager& operator=(T t)
{ v_ = std::move(t); return *this; }
const char* name()
{ return boost::apply_visitor(NameVisitor(), v_); }
private:
variant_type v_;
};
Note: by using variant, you no longer need a base class or virtual functions.
The way you are trying to do it, you are going to get a dangling reference. Having the std::move is just hiding that.
Generally I just structure the code so that the logic is in a separate function. That is, instead of
void f(bool flag)
{
Base &b = // some magic to choose which derived class to instantiate
// do something with b
}
I do
void doSomethingWith(Base &b)
{
// do something with b
}
void f(bool flag)
{
if (flag) {
D1 d1;
doSomethingWith(d1);
}
else {
D2 d2;
doSomethingWith(d2);
}
}
However, if that doesn't work for you, you can use a union inside a class to help manage it:
#include <iostream>
using std::cerr;
struct Base {
virtual ~Base() { }
virtual const char* name() = 0;
};
struct Derived1 : Base {
Derived1() { cerr << "Constructing Derived1\n"; }
~Derived1() { cerr << "Destructing Derived1\n"; }
virtual const char* name() { return "Derived1"; }
};
struct Derived2 : Base {
Derived2() { cerr << "Constructing Derived2\n"; }
~Derived2() { cerr << "Destructing Derived2\n"; }
virtual const char* name() { return "Derived2"; }
};
template <typename B,typename D1,typename D2>
class Either {
union D {
D1 d1;
D2 d2;
D() { }
~D() { }
} d;
bool flag;
public:
Either(bool flag)
: flag(flag)
{
if (flag) {
new (&d.d1) D1;
}
else {
new (&d.d2) D2;
}
}
~Either()
{
if (flag) {
d.d1.~D1();
}
else {
d.d2.~D2();
}
}
B& value()
{
if (flag) {
return d.d1;
}
else {
return d.d2;
}
}
};
static void test(bool flag)
{
Either<Base,Derived1,Derived2> either(flag);
Base &b = either.value();
cerr << "name=" << b.name() << "\n";
}
int main()
{
test(true);
test(false);
}
gives this output:
Constructing Derived1
name=Derived1
Destructing Derived1
Constructing Derived2
name=Derived2
Destructing Derived2
You can ensure you have enough space for allocating either on the stack with std::aligned_storage. Something like:
// use macros for MAX since std::max is not const-expr
std::aligned_storage<MAX(sizeof(D1), sizeof(D2)), MAX(alignof(D1), alignof(D2))> storage;
Base* b = nullptr;
if (flag)
b = new (&storage) D1();
else
b = new (&storage) D2();
You can make a wrapper type for aligned_storage that just takes two types and does the maximum of size/alignment of the two without needing to repeat yourself in the code using it. You can emulate aligned_storage for non-over-aligned types fairly trivially too if you need C++98 support. The custom type without over-aligned support would be something like:
template <typename T1, typename T2>
class storage
{
union
{
double d; // to force strictest alignment (on most platforms)
char b[sizeof(T1) > sizeof(T2) ? sizeof(T1) : sizeof(T2)];
} u;
};
And that can be given protections against copies/moves if you so wish. It can even be turned into a simplified Boost.Variant with relatively little work.
Note that with this approach (or some of the others), destructors will not be called automatically on your class and you must call them yourself. If you want RAII patterns to apply here, you can extend the example class above to store a deleter function that is bound during construction into the space.
template <typename T1, typename T2>
class storage
{
using deleter_t = void(*)(void*);
std::aligned_storage<
sizeof(T1) > sizeof(T2) ? sizeof(T1) : sizeof(T2),
alignof(T1) > alignof(T2) ? alignof(T1) : alignof(T2)
> space;
deleter_t deleter = nullptr;
public:
storage(const storage&) = delete;
storage& operator=(const storage&) = delete;
template <typename T, typename ...P>
T* emplace(P&&... p)
{
destroy();
deleter = [](void* obj){ static_cast<T*>(obj)->~T(); }
return new (&space) T(std::forward<P>(p)...);
}
void destroy()
{
if (deleter != nullptr)
{
deleter(&space);
deleter = nullptr;
}
}
};
// usage:
storage<D1, D2> s;
B* b = flag ? s.emplace<D1>() : s.emplace<D2>();
And of course that can all be done in C++98, just with a lot more work (especially in terms of emulating the emplace function).
How about
B&&b = flag ? static_cast<B&&>(D1()) : static_cast<B&&>(D2());
If you just need them to be freed when the reference goes out of scope, you could implement another simple class (maybe named DestructorDecorator) that points to the object (D1 or D2). And then you just have to implement ~DestructorDecorator to call the destructor of D1 or D2.
You haven't mentioned it, your flag is known at compile time?
As far as a compile-time flag is concerned, you can use template magic to deal with the conditional construction of the class:
First, declaring a template create_if which takes two types and a boolean:
template <typename T, typename F, bool B> struct create_if {};
Second, specializing create_if for true and false values:
template <typename T, typename F> struct create_if<T, F, true> { using type = T; };
template <typename T, typename F> struct create_if<T, F, false> { using type = F; };
Then, you can do this:
create_if<D1, D2, true>::type da; // Create D1 instance
create_if<D1, D2, false>::type db; // Create D2 instance
You can change the boolean literals with your compile-time flag or with a constexpr function:
constexpr bool foo(const int i) { return i & 1; }
create_if<D1, D2, foo(100)>::type dc; // Create D2 instance
create_if<D1, D2, foo(543)>::type dd; // Create D1 instance
This is valid only if the flag is known at compile time, I hope it helps.
Live example.
I'm trying to use move semantics (just as an experiment).
Here is my code:
class MyClass {
public:
MyClass(size_t c): count(c) {
data = new int[count];
}
MyClass( MyClass&& src) : count(src.count) {
data = src.data;
src.count = 0;
src.data = nullptr;
}
void operator=( MyClass&& src) {
data = src.data;
count = src.count;
src.count = 0;
src.data = nullptr;
}
~MyClass() {
if (data != nullptr)
delete[] data;
}
int* get_data() const {
return data;
}
size_t get_count() const {
return count;
}
private:
MyClass(const MyClass& src) : count(src.count) {
data = new int[src.count];
memcpy(data, src.data, sizeof(int)*src.count);
}
void operator=(const MyClass& src) {
count = src.count;
data = new int[src.count];
memcpy(data, src.data, sizeof(int)*src.count);
}
int* data;
size_t count;
};
int main()
{
MyClass mc(150);
for (size_t i = 0; i < mc.get_count(); ++i)
mc.get_data()[i] = i;
MyClass &&mc2 = std::move(mc);
return 0;
}
But std::move does not move mc to mc2, it just copies (copyies pointer as it is). If I remove copy constructor compiler generates it for MyClass.
How can I force move semantics to be used? How can I make it to be used in such constructions:
MyClass mc2(mc); //Move, not copy
-or-
MyClass mc2 = mc; //Move, not copy
I tried to use a '&&' operator to explicitely mark rvalue, but, of cause, it didn't work.
You're declaring m2 as a reference, not as a value. So it still refers to what it was initialised with, namely m1. You wanted this:
MyClass mc2 = std::move(mc);
Live example
As for the second part - there is no way to force a construct like these:
MyClass mc2(mc); //Move, not copy
//-or-
MyClass mc2 = mc; //Move, not copy
to move. If you want to move from an lvalue (and mc is indeed an lvalue), you have to use std::move (or another cast to rvalue) explicitly.
There is one thing you could do, but it would be a dirty hack, make the code unintuitive and be a great source for bugs. You could add an overload of the copy constructor (and copy assignment operator) taking a non-const reference, which would do the move. Basically something like std::auto_ptr used to do before it was rightfully deprecated. But it would never pass code review with me, for example. If you want to move, just std::move.
A few side notes:
Calling delete or delete[] on a null pointer is guaranteed to be a no-op, so you can safely drop the if from your destructor.
It's generally preferable to use std::copy instead of memcpy in C++ code, you don't have to worry about getting the sizeof right
You can force move semantics, if you delete the copy constructor and the assignment operator
MyClass(const MyClass& src)= delete;
void operator=(const MyClass& src) = delete;
in this case the provided move constructor or move assignment operator will be picked.
Rewrite your class a bit with some comments. Look over it, you might notice a few things you missed. Like:
in MyClass(size_t c) not checking for c != 0.
in void operator=(const MyClass& src) not delete[] data; (if exists) before reallocating.
And some other tiny details.Hope your compiler can handle this.
class MyClass {
private:
// initialize memebers directly
int* data = nullptr;
size_t count = 0;
public:
// default empty contructor
MyClass() = default;
// destructor
~MyClass() {
*this = nullptr; // use operator = (nullptr_t)
}
// allow nullptr construct
MyClass(nullptr_t):MyClass() {}
// allow nullptr assignment (for clearing)
MyClass& operator = (nullptr_t) {
if(data) {
delete[] data;
data = nullptr;
}
count = 0;
return *this;
}
// chain to default constructor, redundant in this case
MyClass(size_t c):MyClass() {
// maybe size_t is 0?
if(count = c) {
data = new int[count];
}
}
// chain to default constructor, redundant in this case
MyClass(MyClass&& src):MyClass() {
*this = std::move(src); // forward to move assignment
}
MyClass& operator=(MyClass&& src) {
// don't swap with self
if(&src != this) {
// it's better to swap and let src destroy when it feels like it.
// I always write move contructor and assignment to swap data.
// it's gonna be destroyed anyway, or not...
std::swap(src.data, data);
std::swap(src.count, count);
}
return *this;
}
MyClass(const MyClass& src):MyClass() {
*this = src; // forward to copy assignment
}
MyClass& operator = (const MyClass& src) {
// don't copy to self
if(&src != this) {
// delete first
if(data) {
delete[] data;
data = nullptr;
}
// now reallocate
if(count = src.count) {
data = new int[count];
memcpy(data, src.data, sizeof(int)* count);
}
}
return *this;
}
// easy way to use the object in a if(object) to test if it has content
explicit operator bool() const {
return data && count;
}
// same as above but made for if(!object) to test if empty
bool operator !() const {
return !data || !count;
}
public:
int* get_data() const {
return data;
}
size_t get_count() const {
return count;
}
// add more custom methods
};
Now to move you do this:
MyClass object1; // default construct
MyClass object1(5); // construct with capacity
MyClass object2(object1); // copy constructor
MyClass object3(std::move(object1)); // move constructor
object2 = object1; // copy assignment
object3 = std::move(object1); // move constructor
std::swap(object2, object3); // swap the two
object2 = nullptr; // to empty it
if(object1); // bool cast