Shared posts

12 Apr 05:40

CPPP

by Jonathan Boccara

Here is an exciting piece of news for the C++ community: the CPPP conference has been officially announced!

CPPP is a C++ conference in Paris. Even if you can parse its acronym as “C++ Paris”, this is not what is stands for. It stands for “C++ Progress-Produce-Push forward”. Those are the 3 tracks of the conference.

They have a cool logo:

cppp

Here are the themes of the three tracks:

Progress, as in we all need to progress with C++, and CPPP has a track for beginners or for those who would like to consolidate their basics of C++. But not their basics of French though, because it is a track in French (this is the only track in French).

Produce, as in for the people that work with C++ in the software industry, and who would benefit from practical guidelines, advice and techniques to be more productive with C++ in their everyday job.

Push forward, for the more hardcore C++ enthusiasts who like to push the language beyond its boundaries and accomplish technical prowesses with it.

We’re all a bit of the three I guess, so I’d expect most people to navigate between the three tracks during the conference.

The date is June 15, 2019. It’s coming up quickly!

For more info, check out the CPPP website, and don’t forget that, beyond the conference itself, you’ll have a chance to use this professional trip to spend a bit of time in one of the most beautiful cities in the world…

Become a Patron!
Share this post! Facebooktwittergoogle_pluslinkedin&nbsp&nbsp&nbsp&nbspDon't want to miss out ? Follow: &nbsp&nbsptwitterlinkedinrss

The post CPPP appeared first on Fluent C++.

11 Dec 08:49

Overview of std::map’s Insertion / Emplacement Methods in C++17

by Jonathan Boccara

Today’s guest post is written by @walletfox, one of the hitchhikers in the C++ galaxy, trying to navigate its dark corners by writing articles, creating Mostly Harmless cheat sheets and observing the following rules: “Don’t panic! Always carry a cheat sheet next to the towel. So long and thanks for all the fish.”.

Interested in writing on Fluent C++ too? Submit your post!

TL;DR Go ahead and try out the C++17 emplacement / insertion methods. They offer a tangible improvement in terms of expressiveness and code safety.

insert_or_assign try_emplace map C++

Here are examples of code using them.

C++17 introduced two new insertion / emplacement methods for std::map, namely try_emplace() and insert_or_assign().

At first sight, this might seem like a cause for concern. Why new insertion methods? Don’t we have already plenty of them?

Nevertheless, by studying the problem closer we might come to the conclusion that the introduction of the new methods try_emplace() and insert_or_assign() makes a convincing case and that they bring us closer to more expressive and safer code.

To understand how we ended up with this pool of insertion / emplacement methods, we are going to use a simple map<int, std::string>. Later on, we are going to look at a more complex scenario with std::map<int, A> where A is a struct with two member variables (std::string, int).

For logging purposes I have provided all the special member functions for the struct A. In production, we should apply The Rule of Zero (C++ Core Guidelines, C.20: If you can avoid defining default operations, do) and let the compiler generate the special member functions for us.

Unless stated otherwise, the code was compiled with gcc 9.0.0. and clang 8.0.0, -O2 (HEAD at the time of writing).

struct A
{
    std::string name;
    int age;

    // introduced for logging purposes only
    A(){
        std::cout << "Default ctor. ";
    }

    //explicit
    A(std::string const& s, int x):name(s), age(x){
        std::cout << "Ctor. ";
    }

    A(A const& a):name(a.name),age(a.age){
        std::cout << "Copy ctor. ";
    }

    A(A && a) noexcept :name(std::move(a.name)),age(std::move(a.age)){
        std::cout << "Move ctor. ";
    }

    A& operator=(A const& a){
        std::cout << "Copy assign. ";
        name = a.name;
        age = a.age;
        return *this;
    }

    A& operator=(A && a) noexcept {
        std::cout << "Move assign. ";
        name = std::move(a.name);
        age = std::move(a.age);
        return *this;
    }

    ~A() noexcept {
        std::cout << "Dtor. ";
    }
};

Pre-C++11 days: operator[] and insert()

Before we can discuss how exactly the new  C++17 methods try_emplace() and insert_or_assign() bring improvement, we are going to travel back to pre-C++11 times when all we had was operator[] and insert().

The selling point of operator[] was its simplicity of use, which unlike insert() didn’t need to use std::make_pair() or other verbose constructs to pass around function arguments.

insert_or_assign try_emplace map C++

Fig. 1: The difference between the original insertion methods, C++03

// C++03 style
std::map<int, std::string> m;
m[1] = "Ann";

// C++03 style
std::map<int, std::string> m;
m.insert(std::make_pair(1, "Ann"));
Convenience aside, what is more important, operator[] differs from insert() in how it handles a situation when an element with the given key already exists in the map. While operator[] simply overwrites the corresponding value, insert() doesn’t.
// C++11 style further ahead
auto m = std::map<int, std::string>{{1, "Ann"}};
m[1] = "Ben";
assert(m.at(1) == "Ben");

auto m = std::map<int, std::string>{{1, "Ann"}};
m.insert({1,"Ben"});
assert(m.at(1) == "Ann");
Another important difference lies in the requirements on the value_type, namely, operator[] requires a DefaultConstructible value_type, which means that if we explicitly or implicitly disable the default constructor of the struct A, the code won’t compile. Notice that, unlike insert(),  operator[] calls different special member functions, i.e. the call to the default constructor is followed by the call to copy/move assignment operator.
// Ctor. Default ctor. Move assign. Dtor. Dtor.
auto m = std::map<int, A> {};
m[1] = A("Ann", 63);

// Ctor. Move ctor. Move ctor. Dtor. Dtor. Dtor.
auto m = std::map<int, A> {};
m.insert({1, A("Ann", 63)});
Last but not least, these methods differ in the return information they provide. With operator[], we have no way of finding out whether the insertion actually took place, unless we perform a prior lookup. On the other hand, insert() returns a pair<iterator, bool> that provides us with this information.

Most recently, this has been simplified thanks to structured bindings introduced in C++17.

// C++17 structured bindings style
auto[it, ins] = m.insert({2, "Ann"});

C++11: move semantics and in-place construction

Further down the road, we got C++11 which introduced move semantics, and both operator[] and insert(), i.e. the original insertion methods, benefited from this in terms of performance. In addition, C++11 introduced emplace() which has the same functionality as insert() but additionally, enables in-place construction.

insert_or_assign try_emplace map C++

Fig. 2: Introduction of emplace(), C++11

In-place construction is a technique that bypasses construction and destruction of temporaries by constructing the objects directly in the map. A notable attraction of emplace() is that we can do away either with std::make_pair() or the extra pair of {} that needed to be used with insert(). Emplacement is accomplished via perfect forwarding and variadic templates.

The jury is still out on whether emplace() should be generally preferred to insert(). The potential performance gain is dependent on the types involved and specific library implementations. While Scott Meyers is in favor of emplace() (Effective Modern C++, Item 42, what a coincidence!), other C++ experts/guidelines are in favor of insert(), most notably Bjarne Stroustrup and Abseil Common Libraries. The reason for that is code safety.

Clang-tidy uses a mixed approach with a general preference for emplacement with the exception of std::unique_ptr and std::shared_ptr where emplacement could lead to memory leaks:

// might leak if allocation fails due to insufficient memory for an object A
std::map<int, std::unique_ptr<A>> m;
m.emplace(1, std::make_unique<A>("Ann",63));

Let’s get back to our example and study the effect of different insertion/emplacement constructs. Though this will provide us with some observations, keep in mind that this is a specific example. The types and specific libraries involved are likely to cause differences and it would be counterproductive to make general conclusions. If in doubt, measure.

auto m = std::map<int, A> {};

// (1) Ctor. Copy ctor. Move ctor. Dtor. Dtor. Dtor.
m.insert({1, {"Ann", 63}});

// (2) Ctor. Move ctor. Move ctor. Dtor. Dtor. Dtor.
m.insert(std::make_pair(1, A("Ann", 63)));

// (3) Ctor. Move ctor. Move ctor. Dtor. Dtor. Dtor.
m.insert({1, A("Ann", 63)});

// (4) Ctor. Move ctor. Move ctor. Dtor. Dtor. Dtor.
m.emplace(std::make_pair(1, A("Ann", 63))):

// (5) Ctor. Move ctor. Dtor. Dtor.
m.emplace(1, A("Ann", 63)):

// (6) Doesn't compile. That is why try_emplace of C++17 is of interest
// m.emplace(1, "Ann", 63);

// (7) Ctor. Dtor.
m.emplace(std::piecewise_construct,
std::forward_as_tuple(1),
std::forward_as_tuple("Ann", 63));

Now that we have listed some common alternatives, notice that scenario (1) resulted in a copy constructor call with both compilers. This is because of copy-list-initialization.

// (1) Ctor. Copy ctor. Move ctor. Dtor. Dtor. Dtor.
m.insert({1, {"Ann", 63}});

If performance is of concern, we can disable this alternative by marking the multi-argument constructor of struct A explicit. This code will then fail to compile:

explicit A(std::string const& s, int x):name(s), age(x){
std::cout << "Ctor. ";
}

// won't compile now, copy-list-initialization prevented
m.insert({1, {"Ann", 63}});

It appears that omitting make_pair() with emplace() in case (5) helped us dispense with one move construction, but we can do even better—this is demonstrated in case (7) where we passed std::piecewise_construct and std::forward_as_tuple as arguments to emplace() resulting in a single constructor and destructor call, completely avoiding intermediate copies and moves!

The verbosity of emplacement with piecewise construct is off-putting, therefore you might appreciate C++17’s try_emplace() which will do away with the gobbledegook. This is going to be demonstrated in the next section.

For reasons of completeness, I am also listing scenarios where we move from L-values. As you can see,  contrary to the previous example, we don’t get the same benefit with emplace() and piecewise construct as before.

auto m = std::map<int, A> {};
auto a = A("Ann", 63);

// Ctor. Move ctor. Move ctor. Dtor. Dtor. Dtor.
m.insert(std::make_pair(1, std::move(a)));

// Ctor. Move ctor. Move ctor. Dtor. Dtor. Dtor.
m.insert({1, std::move(a)});

// Ctor. Move ctor. Dtor. Dtor.
m.emplace(1, std::move(a));

// Ctor. Move ctor. Dtor. Dtor.
m.emplace(std::piecewise_construct,
          std::forward_as_tuple(1),
          std::forward_as_tuple(std::move(a)));

C++17: try_emplace() and insert_or_assign() as a solution to double lookup

Now we have enough background to understand the rationale behind the introduction of the new methods. try_emplace() and insert_or_assign() differ in their respective functionalities, but they do have something in common—they are both a solution to a redundant search that had to be performed in pre-C++17 days to provide safety or additional information.

insert_or_assign try_emplace map C++

Fig. 3 C++17’s try_emplace() and insert_or_assign()

try_emplace()

try_emplace() is a safer successor of insert() or emplace(). In line with insert() and emplace(), try_emplace() doesn’t modify values for already inserted elements. However, on top of that, it prevents stealing from original arguments that happens both with insert() and emplace() in case of a failed insertion.

This is demonstrated in the snippet below. An element with key 1 is already in the map, as a result p1 won’t be inserted. That doesn’t prevent emplace() from plundering the pointer p:

auto m = std::map<int, std::unique_ptr<A>> {};
m.emplace(1, std::make_unique<A>("Ann",63));

auto p = std::make_unique<A>("John",47);
// p won't be inserted
m.emplace(1, std::move(p));

//but it still might get plundered!!!
assert(p != nullptr); // this will most likely fail

In the pre C++17 days this issue could have been only solved with a prior lookup, with find().

auto it = m.find(1);
// call emplace only if key doesn’t exist
if (it == m.end()) {
    it = m.emplace(1, std::move(p)).first;
}
assert(p != nullptr);

This lookup is no longer necessary. try_emplace() makes sure that the argument remains untouched in case it wasn’t inserted:

m.try_emplace(1, std::move(p));
// no plundering in case insertion failed
assert(p != nullptr);

Although this is the primary purpose of try_emplace(), there are some other important advantages. As already mentioned in the previous section, try_emplace() simplifies the original emplace() that had to use pair’s piecewise constructor:

// before C++17
auto m = std::map<int, A> {};
m.emplace(std::piecewise_construct,
          std::forward_as_tuple(1),
          std::forward_as_tuple("Ann", 63));

and dispenses with its verbosity in the following way:

// C++17
auto m = std::map<int, A> {};
m.try_emplace(1, “Ann”, 63);

At first sight, using try_emplace() in this way might seem rather user unfriendly due to the nonexistent boundary between the key and the value. However, if used in this way, try_emplace() solves another issue of emplace(), namely that objects were created even though they weren’t actually used.

Specifically, the map below already contains the key 1 with value {“Ann”, 63}, thus a {“Ben”, 47} object doesn’t need to be generated, because emplace() doesn’t modify values for already existing keys.

// std::map m with the original object
auto m = std::map<int, A> {};
m.emplace(1, A("Ann", 63));

// doesn't generate a redundant object
m.try_emplace(1, "Ben", 47);

Nonetheless, we shouldn’t  blindly replace all occurrences of emplace() with try_emplace() without adjusting the argument list first. The try_emplace() that uses A’s constructor below generates a redundant object just like its emplace() counterparts:

// Ctor. Dtor. - redundant object
m.try_emplace(1, A("Ben", 47));

// Ctor. Move ctor. Dtor. Dtor.  - redundant object
m.emplace(1, A("Ben", 47));

// Ctor. Dtor. - redundant object
m.emplace(std::piecewise_construct,
std::forward_as_tuple(1),
std::forward_as_tuple("Ben", 47));

insert_or_assign()

insert_or_assign() is a “smarter” successor of operator[]. Just like operator[] it modifies values if supplied with a key that is already present in the map. However, unlike operator[], insert_or_assign() doesn’t require default constructibility of the value_type. On top of that, it returns a pair<iterator, bool>. The bool is true when insertion took place and false in case of assignment.

Again, this information was unavailable for operator[] without a prior lookup with the help of find() as demonstrated below. The map already contains an element with the key 1, thus this won’t be an insertion but an update.

auto m = std::map<int, std::unique_ptr<A>> {};
m[1] = std::make_unique<A>("Ann",63);

auto p = std::make_unique<A>("John",47);

auto key = int{1};
auto ins = bool{false};

auto it = m.find(key);
if(it == m.end()){
    ins = true;
}

m[key] = std::move(p);
assert(ins == false);

The code contains a lot of boilerplate that can result both in errors and performance inefficiencies only for the sole purpose of insert or update identification. Luckily, with insert_or_assign() we can skip all of it and simply write:

auto[it, ins] = m.insert_or_assign(1, std::move(p));
assert(ins == false);

Difficulties with inferring from names

At present, it is difficult to conclude whether the new C++17 methods express clearly their intent and functionality. If you have a look at the original proposal, try_emplace() is being referred to as emplace_stable(), while insert_or_assign() is being referred to as emplace_or_update().

At the moment it might seem confusing but with more frequent use we are bound to get it right and hopefully, we will be able to link the new names to the correct functionalities.

Summary

Remember that:

  • insert(), emplace() and try_emplace() don’t overwrite values for existing keys. On the other hand, operator[] and insert_or_assign() overwrite them.
  • emplace() may be susceptible to memory leaks if allocation fails.
  • try_emplace() doesn’t steal from original arguments if insertion fails. This is in contrast to emplace() and insert().
  • try_emplace() doesn’t generate redundant objects in case insertion didn’t take place. This is in contrast to emplace().
  • try_emplace() offers a simplified piecewise construction. On the other hand, emplace() has to use std::piecewise_construct, std::forward_as_tuple.
  • insert_or_assign() doesn’t require default constructibility. On the other hand, operator[] does.
  • insert_or_assign() returns information on whether insertion or assignment took place. This is in contrast to operator[].

The author is grateful to Jonathan Boccara for hosting, formatting and editing the post and Ricardo Nabinger Sanchez for proofreading.

You will also like

Become a Patron!
Share this post! Facebooktwittergoogle_pluslinkedin&nbsp&nbsp&nbsp&nbspDon't want to miss out ? Follow: &nbsp&nbsptwitterlinkedinrss

The post Overview of std::map’s Insertion / Emplacement Methods in C++17 appeared first on Fluent C++.

19 Sep 06:35

Samsung launches an official site to see if your Galaxy Note 7 needs to be replaced (and an Android app, too)

by Quentyn Kennemer
With yesterday's official recall going underway we have a more formal and official method of checking Galaxy Note 7 devices. Check to see if yours is affected!
24 Dec 09:13

Score Free In-Game Lunchboxes in Fallout Shelter with NVIDIA SHIELD Tablet K1

by Phandroid Sponsor

Grab yourself a SHIELD Tablet K1 and you get two things. First you get a gaming platform with a crisp HD screen and unmatched power thanks to the onboard NVIDIA Tegra K1 processor. Second, you get a brilliant little game called Fallout Shelter pre-loaded onto your new tablet—along with free in-game loot—so you can experience all the fun of a nuclear winter straight out of the box.

Exclusively available to SHIELD Tablet K1 owners, NVIDIA is giving away a free bundle of five Lunchboxes in Fallout Shelter to the first 50,000 players who register. To redeem your in-game prize, go to the Settings app on your SHIELD Tablet K1, tap About Tablet, then tap Status and then copy your device’s serial number and enter it into this redemption page.

If the word Fallout is ringing all sorts of bells it’s because this is a spinoff of the much bigger franchise that appears on consoles and desktop gaming rigs. In the games from the main series you have to learn to cope once you leave the fallout shelter, in this game, you play the part of an overseer who has to manage an underground bunker, nurturing and protecting the people living in it.

screenshot03_3145

You shelter begins modestly enough with a single reception area and a few lift shafts. It’s not much good for sustaining an underground society so the first job is to get building.

From the build menu you can begin to dig out and create new rooms such as power plants, water refinement plants, diners and living quarters. As citizens from the wasteland rock up outside the vault’s main entrance, it’s your job to look at their stats to ascertain their strengths and then assign them to rooms so that they can start to generate resources for the community such as power, food and water.

screenshot01_3499

This basic balancing act may seem relatively straightforward, but the idea is to keep growing your shelter and increasing your population so things soon get more complex. Building new rooms can be a slow process and it takes awhile to yield the resources you need so you can spend your in-game currency on the Rush option, which allows you to complete tasks quickly. Rushing a job though, carries risk. For example, putting a rush on your power plant could result in a fire, so you have to very carefully assess whether rushing for short-term gains is worth it.

As well as keeping your citizens fed and watered, you must also keep them healthy and happy. From the build menu you can access a large number of facilities in order to fulfill these needs but they only become available to you as your population reaches certain target numbers. Ultimately you will be able to add Med bays, labs, gymnasiums classrooms and gardens. In this way you can add more and more capacity for citizens to survive and thrive.

screenshot02_3258

It all sounds quite idyllic, albeit a little claustrophobic, but it’s by no means all plain sailing. The task of maintaining the welfare of your underground colony is in itself a challenge and more so as it grows ever large. But there’s also the ever-present threat from the Wasteland outside. Not all the resources can be found underground. Additional loot, armor and weapons need to be recovered from the barren surface and to this end you can send your citizens outside to do just that, but they may face an untimely death at the hands of raiders so it’s also necessary to assign some of your citizens to guard duty.

It’s a fascinating process that starts out simply allowing you to grow your vault at your own pace before adding more and more complexity to your subterranean society. The visual design is beautiful too. Every little citizen is expertly animated and the vault itself is crammed with numerous details that really come to life on the SHIELD Tablet K1’s HD screen. The fact that it comes free is the icing on the cake.

Get Fallout Shelter on NVIDIA SHIELD Tablet K1 now.

About the Author

Andy_DyerAndy has been writing professionally for 25 years beginning his career on a magazine for the now practically antique Commodore 64 before going on to write for, edit and launch a number of games titles. More recently, as a freelance copy writer he has been making words on subjects as diverse as weddings, cross-stitching, home improvements, accountancy, architecture and chimney sweeps. Video games remain his favorite topic to write about, though.

12 Dec 14:35

Plastc wants to be the only credit card you'll ever need

by Mariella Moon

Your fat wallet wants to meet Plastc -- a device which its manufacturers claim can replace most of the credit/gift/loyalty cards you currently mule about. It works by pairing with an app on your phone (via Bluetooth), which provides near unlimited storage for all your cards (Plastc itself can only store up to 20). The app also logs your transaction history. Does this all sound a little familiar? That's because you're probably recalling a similar device called Coin launched back in 2013. Just like Plastc, it, too, can store various card details that you can call up, depending on which one you want to use. The bad news is that Coin, which promised to ship the first units this year, moved its ETA to spring 2015 (though there's a beta test going on) -- something pre-order customers obviously weren't happy with. So, one has to wonder if an unknown company will be able to do what Coin couldn't and release such an ambitious product on time?

See, in addition to being able to switch up card details through the e-ink touchscreen panel, Plastc can also show loyalty or gift cards' barcodes and remotely wipe your data in case it gets lost or stolen. The panel displays your name, picture and signature along with your card number as a form of identification, and it even flashes a message to return the card back to you if you lose it. Its accompanying app, on the other hand, is supposed to come with a security pin and facial authentication.

If both Plastc and Coin do make it to market, though, the former might have the upper hand, as it'll come embedded with a computer chip that makes it difficult to clone. The US will start encouraging retailers to only accept cards with those chips by 2015, making Coin obsolete almost as soon as it's out. Plastc's now available for pre-order from its website for $155 each -- $55 more expensive than the $100 Coin -- and might be out as soon as the summer of 2015.

Filed under: Misc, Mobile

Comments

Source: Plastc