class with unique_ptr problems - c++

When using emplace_back a constructor must exist for the parameters passed (k,v) thus I need the constructor below. However since I use unique_ptr it complains about not being able to access 'delete' which I believe means I'm doing something that allows me to have more then one pointer.
I can't figure out the syntax. How do I write this constructor the right way?
struct KV{
unique_ptr<string> k, v;
KV(){}
KV (unique_ptr<string> k_,unique_ptr<string> v_):k(move(k_)),v(move(v_)){}
};

Your constructor is OK. A possible problem is that you are not moving the two unique_ptrs when supplying them to your constructor:
#include <memory>
#include <string>
using namespace std;
struct KV{
unique_ptr<string> k, v;
KV(){}
KV (unique_ptr<string> k_,unique_ptr<string> v_):k(move(k_)),v(move(v_)){}
};
int main()
{
unique_ptr<string> p1(new string());
unique_ptr<string> p2(new string());
// KV v(p1, p2); // ERROR!
KV kv(move(p1), move(p2)); // OK
vector<KV> v;
v.emplace_back(move(p1), move(p2)); // OK
}
UPDATE:
When VS2012 was shipped, VC11 did not support variadic templates. The correct implementation of emplace_back() should be variadic, but MS provided a dummy one. When the CTP has been shipped, only the compiler has been updated with support for variadic templates, but the STL hasn't been updated. Therefore, you still get the error.
There is not much to do about this if you can't change your compiler, apart from waiting for the next release of the product to be shipped. In the meanwhile, avoid using emplace_back() and use push_back() instead.

You haven't mentioned what container you're trying to emplace_back into, but assuming it is a vector, if your KV struct is really that simple, there's no need to declare any constructors. Just use aggregate initialization.
#include <memory>
#include <string>
#include <utility>
#include <vector>
using namespace std;
struct KV
{
unique_ptr<string> k, v;
// KV(){}
// KV (unique_ptr<string> k_,unique_ptr<string> v_):k(move(k_)),v(move(v_)){}
};
int main()
{
unique_ptr<string> p1(new string());
unique_ptr<string> p2(new string());
KV v{move(p1), move(p2)}; // initialize an instance
// this step is not necessary, you can skip it
vector<KV> vec;
vec.emplace_back(KV{move(v.k), move(v.v)});
}

Related

NRVO of std::array in constructor initialiser list

I know std::array doesn't do move semantics because it's not dynamically allocated. Do Compilers do proper NRVO for it? What about in the context of the calling code being a constructor initializer list?
Code is below and on goldbolt here: https://godbolt.org/z/je1Mvj15P
NB The share link passes argv[1] = "12345678901234567890". Also it is using only -Og to keep the assembly readable. At -O3 it starts unrolling loops etc, but this does not affect the question I believe.
The constructor init list call arr_(get_arr(s)) has no choice but to copy, because move its not available. Unless the compiler is doing full NRVO (which is "not mandatory", see comments below).
The compiler explorer output seems to show no copying to my eyes.
Is NRVO saving this?
Is this idiomatic / good? Or is std::array the wrong choice here? Or maybe this way of initialising an non-movable aggregate member with a function call and therefore relying on RVO is not sensible/reliable?
Would it be better to leave arr_ uninitialised in the constructor init list and move the code from get_arr into the constructor body? Like this: https://godbolt.org/z/jxv69YvK3
#include <algorithm>
#include <array>
#include <numeric>
#include <string>
std::array<std::byte, 20> get_arr(const std::string& s) {
std::array<std::byte, 20> a;
// a silly proxy algorithm for the real thing
std::transform(s.begin(), s.end(), a.begin(), [](auto b) { return std::byte(unsigned(b) << 1U); });
return a;
}
struct S {
explicit S(const std::string& s) : arr_(get_arr(s)) {}
std::array<std::byte, 20> arr_;
};
int main(int /*argc*/, char* argv[]) {
// in reality we are reading about 600'000'000 strings from a file
S s(argv[1]);
return static_cast<int>(s.arr_[19]); // use it to avoid optimising away
}

Simplest way to assign std::span to std::vector

I wanted to do this
#include <vector>
#include <span>
struct S
{
std::vector<int> v;
void set(std::span<int> _v)
{
v = _v;
}
};
But it does not compile. What are the alternatives?
v.assign(_v.begin(), _v.end());
You can also use the std::vector::insert as follows:
v.insert(v.begin(), _v.begin(), _v.end());
Note that, if the v should be emptied before, you should call v.clear() before this. However, this allows you to add the span to a specified location in the v.
(See a demo)

Insert custom class with template into std::map

I have written my own class and I want to insert it into a map. See the example below:
#include <iostream>
#include <string>
#include <map>
#include <memory>
#include <mutex>
template <class T>
class A {
public:
T a;
A() = default;
~A() = default;
A(T i) { a = i; }
};
int main()
{
std::pair<int,A<int>> p;
p = std::make_pair<int,A<int>>(9,A<int>(1));
std::map<int, A<int>> m;
m.emplace(1,A<int>(1));
}
When I try to compile this, I get an enormous error. Please help interpret it. :)
See error here:
http://cpp.sh/9nc35
EDIT:
I had the typo, thanks! Though, the other problem I was struggling with first arose now. Seems like it is because of the mutex? Why?
Your map is defined as:
std::map<int, std::unique_ptr<A<int>>>
But in the next line you're trying to pass an std::pair<int, A<int>> to m.emplace() as the key.
I think you just want to do:
m.emplace(9, std::make_unique<A<int>>(1));
// ^
// Not `p`
You are trying to insert/emplace pair (pair<...>, A) into your map, while you've specified it's key as an int. You most-likely want m.emplace(9,std::make_unique<A<int>>(1)); (see 9 instead of p) or just m.insert(p); (would work fine in your cpp.sh).
Furthermore, your use of unique_ptr here is most-likely wrong/unwarranted and only complicates things. See fixed up example here: http://cpp.sh/3d2hw
Also, you may study STL collections/see some basic examples over at https://en.cppreference.com (https://en.cppreference.com/w/cpp/container/map/map for some map construction examples).

Moving elements from std::vector<T1> to std::vector<std::pair<T1,T2>>

What is the most correct and efficient way to std::move elements from a vector of a certain type (T1) into a vector of an std::pair of that same type (T1) and another type (T2)?
In other words, how should I write MoveItems()?
#include <iostream> // For std::string
#include <string> // For std::string
#include <vector> // For std::vector
#include <utility> // For std::pair
using std::vector;
using std::string;
using std::pair;
vector<string> DownloadedItems;
vector<pair<string,bool>> ActiveItems;
vector<string> Download()
{
vector<string> Items {"These","Words","Are","Usually","Downloaded"};
return Items;
}
void MoveItems()
{
for ( size_t i = 0; i < DownloadedItems.size(); ++i )
ActiveItems.push_back( std::pair<string,bool>(DownloadedItems.at(i),true) );
}
int main()
{
DownloadedItems = Download();
MoveItems();
return 0;
}
Thank you for your time and help, I truly appreciate it!
void MoveItems()
{
ActiveItems.reserve(DownloadedItems.size());
for (auto& str : DownloadedItems)
ActiveItems.emplace_back(std::move(str), true);
}
N.B.: For strings as small as the ones in your example, moving may have the same cost as copying due to SSO, or perhaps even slightly more expensive if the implementation decides to empty out the source anyway.
Some things you can do:
At the start of MoveItems(), call ActiveItems.reserve(DownloadedItems.size());. This prevents your array from resizing while you push things into it.
Instead of calling push_back call emplace_back. Here is an explanation of the advantages of doing so.
Worth noting, in this example, you can stop the copy into a new data structure by just constructing the std::pair from the start, and not copying data.

Avoiding temporary when using boost::optional

boost::optional support in_place construction like so:
#include <boost/optional.hpp>
#include <boost/utility/typed_in_place_factory.hpp>
class Foo
{
int a,b;
public:
Foo(int one, int two) : a(one),b(two) {}
};
int main()
{
boost::optional<Foo> fooOpt(boost::in_place<Foo>(1,3));
}
Once we have an initialized fooOpt, is there a way of assigning a new Foo to it without creating a temporary?
Something like :
fooOpt = boost::in_place<Foo>(1,3);
Thanks!
boost::optional
#include <boost/optional.hpp>
int main() {
boost::optional<int> x;
x = boost::in_place(3);
}
We can also show (via code) that this is building the object in-place by making Foo inherit from boost::noncopyable:
#include <boost/optional.hpp>
#include <boost/noncopyable.hpp>
class Foo : boost::noncopyable {
public:
Foo(int one, int two) {}
};
int main() {
boost::optional<Foo> x;
x = boost::in_place(3, 4);
}
std::optional (eventually...)
Eventually, we will get access to std::optional. This type will implement an emplace() method, that will implement in-place construction as well.
#include <optional>
int main() {
std::optional<int> x;
x.emplace(3);
}
boost::optional (soon...)
In version 1.56.0, boost::optional will also implement the emplace() method that I talked about for std::optional. So, let's see that:
#include <boost/optional.hpp>
int main() {
boost::optional<int> x;
x.emplace(3);
}
The documented interface does not support this.
However, if you know that nobody extends boost::optional, I believe this may be technically valid:
template<typename T, typename... Us>
void emplace_replace( boost::optional<T>& target, Us&&... us ) {
target.~boost::optional<T>();
try {
new (&target) boost::optional<T>( boost::in_place( std::forward<Us>(us)...) );
} catch(...) {
new (&target) boost::optional<T>();
throw;
}
}
Here, we destroy the target, then reconstruct a new boost::optional<T> in its place with in-place construction. The try-catch construct should make most throws during construction safe: if it throws, you end up with an empty optional.
This naturally behaves differently than operator= is expected to.
In 1.55 (and maybe earlier?), there is an undocumented operator= that takes an Expr which supports boost::in_place and boost::in_place<T>. See #sharth's answer for a detailed use.
My quick reading indicates that a typed inplace factory via this method may have insufficient guards:
boost::optional<int> test;
// test = boost::in_place<double>( 3 ); // <-- very dangerous
test = boost::in_place( 3 ); // safe
test = boost::in_place( 3.0 ); // safe
If a type is passed directly to in_place<?>, it can generate a typed_in_place_factory, which are dangerous (they make the passed in type, and don't check that it is compatible). So don't pass any types to boost::in_place.
This (from reading the source) does something similar to my destroy/reconstruct code, except it does it without destroying the entire optional and just destroys the stored data and makes it uninitialized.
In boost 1.56b1, emplace has been added to boost::optional. It does something similar to both of the above operations. (via #AkiraTakahashi)
std::optional proposals I have seen have included a member function .emplace( Us&&... ) that supports emplace replacing directly.
Once you know it's there, you could create an ordinary reference:
optional<Foo> optFoo = ....;
Foo &foo = *optFoo;
foo.x = 3;
foofun(foo);
foo = Foo();