I have a following class:
class Foo
{
public:
void Fill();
private:
std::vector<std::wstring> vec;
};
And then the implementation is:
void Foo::Fill()
{
vec.push_back( L"abc aaa" );
vec.push_back( L"def aaa" );
vec.push_back( L"fed bbb" );
vec.push_back( L"cba bbb" );
}
What I'd like to do to delete an element from this vector, lets say one that contains "def". What would be the easiest way to do so?
I'm thinking to use remove_if, but the comparator accept only 1 parameter - container element.
Is there an elegant solution? I'd use looping as a last resort.
If it's a class rather than a function, the predicate has a constructor, and constructors can take arguments.
You can pass your search string into this constructor, store it as a member, then use it inside the function call operator:
struct Pred
{
Pred(std::wstring str) : str(std::move(str)) {}
bool operator()(const std::wstring& el) const
{
return el.find(str) != el.npos;
}
private:
const std::wstring str;
};
std::remove_if(std::begin(vec), std::end(vec), Pred("def"));
// N.B. `el.find` is probably wrong. Whatever.
A "shortcut" to doing this is to use a lambda for the predicate, then the passing through of the search string is done for you either via the lambda capture, or by virtue of the fact that you literally typed it in right there and then:
std::remove_if(
std::begin(vec), std::end(vec),
[](const auto& el) { return el.find("def") != el.npos; }
);
// N.B. `el.find` is probably still wrong. Whatever.
If the predicate is a function, and you want it to invoke a binary comparator, you could mess about with std::bind to achieve the same result.
Related
Is there a way to implement operator->, not only operator*. To have following code working:
Iterator<value> it = ...
i = (*it).get();
i = it->get(); // also works
Let we say that value type has method get.
When Iterator is implemnted as below:
template<T> class Iterator {
T operator*() { return ... }
T operator->() { return ... }
}
Here ... is an implementation of getting right T object.
Somehow it won't work when I implement it in this way. I think I misunderstand something.
operator-> should return a pointer:
T * operator->();
T const * operator->() const;
operator* should return a reference if you want to use it for modification:
T & operator*();
T operator*() const; // OR T const & operator*() const;
As odd as this may seem, you want to return a pointer to T, thusly:
T * operator->() { return &the_value; }
Or a pointer to const.
You don't specify what "it won't work" means - does it fail to compile, or does something else than expected? I will assume it compiles, because from your snippet I can't see why it shouldn't.
What you are doing is returning by value. So you return a new instance of the pointed-to object. You instead should return a pointer in operator-> and reference in operator*
Regardless of the fact that copying a unique_ptr makes sense or not*, I tried to implement this kind of class, simply wrapping a std::unique_ptr, and got into difficulty exactly where the copy is taken, in the case of a smart pointer to base and the stored object being a derived class.
A naive implementation of the copy constructor can be found all over the internet (data is the wrapped std::unique_ptr):
copyable_unique_ptr::copyable_unique_ptr(const copyable_unique_ptr& other)
: data(std::make_unique(*other.get()) // invoke the class's copy constructor
{}
Problem here is, that due to the left out template arguments, is that the copy creates an instance of the type T, even if the real type is U : T. This leads to loss of information on a copy, and although I understand perfectly well why this happens here, I can't find a way around this.
Note that in the move case, there is no problem. The original pointer was created properly somewhere in user code, and moving it to a new owner doesn't modify the object's real type. To make a copy, you need more information.
Also note that a solution employing a clone function (thus infecting the type T's interface) is not what I would find to be acceptable.
*if you want a single owning pointer to a copyable resource this can make sense and it provides much more than what a scoped_ptr or auto_ptr would provide.
After some struggling with getting all the magic incantations right so that a good C++ compiler is satisfied with the code, and I was satisfied with the semantics, I present to you, a (very barebones) value_ptr, with both copy and move semantics. Important to remember is to use make_value<Derived> so it picks up the correct copy function, otherwise a copy will slice your object. I did not find an implementation of a deep_copy_ptr or value_ptr that actually had a mechanism to withstand slicing. This is a rough-edged implementation that misses things like the fine-grained reference handling or array specialization, but here it is nonetheless:
template <typename T>
static void* (*copy_constructor_copier())(void*)
{
return [](void* other)
{ return static_cast<void*>(new T(*static_cast<T*>(other))); };
}
template<typename T>
class smart_copy
{
public:
using copy_function_type = void*(*)(void*);
explicit smart_copy() { static_assert(!std::is_abstract<T>::value, "Cannot default construct smart_copy for an abstract type."); }
explicit smart_copy(copy_function_type copy_function) : copy_function(copy_function) {}
smart_copy(const smart_copy& other) : copy_function(other.get_copy_function()) {}
template<typename U>
smart_copy(const smart_copy<U>& other) : copy_function(other.get_copy_function()) {}
void* operator()(void* other) const { return copy_function(other); }
copy_function_type get_copy_function() const { return copy_function; }
private:
copy_function_type copy_function = copy_constructor_copier<T>();
};
template<typename T,
typename Copier = smart_copy<T>,
typename Deleter = std::default_delete<T>>
class value_ptr
{
using pointer = std::add_pointer_t<T>;
using element_type = std::remove_reference_t<T>;
using reference = std::add_lvalue_reference_t<element_type>;
using const_reference = std::add_const_t<reference>;
using copier_type = Copier;
using deleter_type = Deleter;
public:
explicit constexpr value_ptr() = default;
explicit constexpr value_ptr(std::nullptr_t) : value_ptr() {}
explicit value_ptr(pointer p) : data{p, copier_type(), deleter_type()} {}
~value_ptr()
{
reset(nullptr);
}
explicit value_ptr(const value_ptr& other)
: data{static_cast<pointer>(other.get_copier()(other.get())), other.get_copier(), other.get_deleter()} {}
explicit value_ptr(value_ptr&& other)
: data{other.get(), other.get_copier(), other.get_deleter()} { other.release(); }
template<typename U, typename OtherCopier>
value_ptr(const value_ptr<U, OtherCopier>& other)
: data{static_cast<pointer>(other.get_copier().get_copy_function()(other.get())), other.get_copier(), other.get_deleter()} {}
template<typename U, typename OtherCopier>
value_ptr(value_ptr<U, OtherCopier>&& other)
: data{other.get(), other.get_copier(), other.get_deleter()} { other.release(); }
const value_ptr& operator=(value_ptr other) { swap(data, other.data); return *this; }
template<typename U, typename OtherCopier, typename OtherDeleter>
value_ptr& operator=(value_ptr<U, OtherCopier, OtherDeleter> other) { std::swap(data, other.data); return *this; }
pointer operator->() { return get(); }
const pointer operator->() const { return get(); }
reference operator*() { return *get(); }
const_reference operator*() const { return *get(); }
pointer get() { return std::get<0>(data); }
const pointer get() const { return std::get<0>(data); }
copier_type& get_copier() { return std::get<1>(data); }
const copier_type& get_copier() const { return std::get<1>(data); }
deleter_type& get_deleter() { return std::get<2>(data); }
const deleter_type& get_deleter() const { return std::get<2>(data); }
void reset(pointer new_data)
{
if(get())
{
get_deleter()(get());
}
std::get<0>(data) = new_data;
}
pointer release() noexcept
{
pointer result = get();
std::get<0>(data) = pointer();
return result;
}
private:
std::tuple<pointer, copier_type, deleter_type> data = {nullptr, smart_copy<T>(), std::default_delete<T>()};
};
template<typename T, typename... ArgTypes>
value_ptr<T> make_value(ArgTypes&&... args)
{
return value_ptr<T>(new T(std::forward<ArgTypes>(args)...));;
}
Code lives here and tests to show how it should work are here for everyone to see for themselves. Comments always welcome.
I have a class with a couple of fields, assignment c-tor and move c-tor:
class A{
std::vector<int> numbers;
int k;
public:
A(std::vector<int> &&numbers, const int k):
numbers(numbers), // fast
k(k)
{
// logic
}
A(const std::vector<int> &numbers, const int k):
A(std::move(std::vector<int>(numbers)), k) // copy-and-move vector
{
// empty
}
};
I want to keep logic in one c-tor and call it from others.
Also, I want to support fast move-semantics. And I have to explicitly copy-and-move arguments in the assignment c-tor.
Is there any way to avoid such nested construction and keep all advantages I've listed above?
You could delegate one constructor to the other:
struct A
{
A(const std::vector<int> & v) : A(std::vector<int>(v)) {}
A(std::vector<int> && v)
: v_(std::move(v))
{
// logic
}
// ...
};
The moving constructor is now as fast as it can be, and the copying constructor costs one more move than if you spell both constructors out. If you're willing to pay an extra move, though, you might as well just have a single constructor:
struct A
{
A(std::vector<int> v)
: v_(std::move(v))
{
// logic
}
};
The alternative is to put the common code into a function and call that from both constructors.
I have a beginner question on the move assigment in c++11. Let say that I have a class A provided with a move assigment operator:
class A
{
public:
A();
~A();
A& operator=(A&&);
...
}
I also have a class B containing a class A object and provided with a move assignment operator
class B
{
public:
B();
~B();
B& operator=(B&&);
...
private:
A Test;
}
What I was thinking is that the B move assignment operator will call the move assignment operator of its member so I tried this method:
B& B::operator=(B&& Other)
{
...
Test = Other.Test;
...
return *this;
}
But this is not working since the move assignment of class A is not called.
Instead I was able to make the program work by using this method:
B& B::operator=(B&& Other)
{
...
Test = std::move(Other.Test);
...
return *this;
}
I do not understand why the first method is not working. I was thinking that since a constructor will call its members constructors the move assignment operator should do the same. Am I wrong or I made a mistake in my code? Can someone explain, thanks!
Other.Test is not an rvalue expression since it has a name. OTOH std::move(Other.Test) has the type A and the value category xvalue (i.e., an rvalue). Thus, it can bind to the move constructor.
(EDIT : Shamelessly copied #dyp's comment. Thanks, #dyp and #KerrekSB.)
#Pradhan is correct - you need to use std::move to move the members in the implementation of the move assignment operator. However, if that is all that is needed to implement your move constructor, then you can declare the operator to use the default implementation:
#include <memory>
class A {
public:
A() : p{} { }
~A() { }
A &operator=(A &&) = default;
// Instead of:
// A &operator=(A &&other) {
// p = std::move(other.p);
// return *this;
// }
private:
std::unique_ptr<int> p;
};
int main() {
A a;
A b;
b = std::move(a);
return 0;
}
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.