I want to print a pair, e.g.
std::cout << make_pair(std::string,int) << endl;
But it doesn't compile because operator<<(ostream &, std::pair<std::string,int>) is not defined.
But because we now have c++11 with lambda functions, I can use lambda functions with a for_each expression to work on containers.
For the above case how could I supply an "in-place method" which can be used by ostream to print the pair?
Pairs (and other tuples) aren't really like containers, because their elements have heterogeneous types. They can't be iterated over in the normal way. So a lambda isn't really applicable here.
If you want, just define an output_pair template function which takes an ostream and a pair, and outputs the two elements of the pair. Or if you wanted to keep the extraction style, you could have output_pair return an output_pair_struct which does nothing but hold a copy of the tuple, and define an operator<< on the output_pair_struct which did the actual work, so that you could have std::cout << output_pair(mypair) << endl;.
For the above case how could I supply an "in-place method" which can be used by ostream to print the pair?
auto print = [&](const std::pair<std::string,int>& p) {
std::cout << p.first << ", " << p.second << "\n";
};
std::map<std::string,int> sequence = { /* ... */ };
for_each(sequence.begin(), sequence.end(), print);
for(const auto& p: sequence)
print(p);
or:
for_each(sequence.begin(), sequence.end(),
[&](const std::pair<std::string,int>& p) {
std::cout << p.first << ", " << p.second << "\n";
});
Either way, this is too complicated. You should write it like this:
for(const auto& p: sequence)
std::cout << p.first << ", " << p.second << "\n";
Related
I have a fairly easy problem: I have an std::map<int,T> and another std::set<int> (can be std::vector or similar too).
In the map I store items, and in the other container I'm storing favorites (of the map).
At some point, I'd need to retrieve (all) items from the map, but starting with the favorites defined by the other container.
Here is my minimal repro, I solved it very ugly, and ineffective:
#include <iostream>
#include <string>
#include <set>
#include <map>
using namespace std;
map<int, string> myMap;
set<int> myFavorites;
int main()
{
myMap.emplace(1, "but I don't like this");
myMap.emplace(12, "So it will go below");
myMap.emplace(31, "This one will come first, and");
myMap.emplace(44, "under my favorites");
myMap.emplace(52, "then this will follow");
myFavorites.insert(52);
myFavorites.insert(31);
cout << "My map:" << endl;
for(auto p : myMap) {
cout << "#" << p.first << "=" << p.second << endl;
}
cout << endl << "My favorites:" << endl;
for(auto p : myFavorites) {
cout << "#" << p << endl;
}
cout << endl << "All items starting with my favorites:" << endl;
for(auto p : myFavorites) {
auto item = myMap.find(p);
if (item != myMap.end()) cout << "#" << item->first << "=" << item->second << endl;
}
for(auto p : myMap) {
if (myFavorites.find(p.first) != myFavorites.end()) continue;
cout << "#" << p.first << "=" << p.second << endl;
}
}
What really bothers me is the last loop, where each iterations would call find on the set.
Required output is:
All items starting with my favorites:
#31=This one will come first, and
#52=then this will follow
#1=but I don't like this
#12=So it will go below
#44=under my favorites
Here is the above source in Coliru for making it easier: https://coliru.stacked-crooked.com/a/731fa76d90bfab00
Both map and set might be changed, but replacements needs to implement the same interfaces as originals.
I'm looking for a way to solve this more efficient than my original "brute-force" one.
Please note: map must not be "reordered"! I just need to query (retrieve) its items with custom sorting!
Note2: I know map can have a comparison operator. But I'd need to have the original order usually, and sometimes I'd need to have the custom sort!
Note3: Boost is not available and compiler is C++14 capable.
Both std::map and std::set use the same strict weak ordering for ordering its contents.
You can take advantage of this. You know that if you iterate over the map you will get the keys in the same order as they are in the set, therefore all it takes is a little bit of clever logic, something like:
auto map_iter=myMap.begin();
for(auto p : myFavorites) {
while (map_iter != myMap.end())
{
if (map_iter->first == p)
cout << "#" << map_iter->first << "=" << map_iter->second << endl;
if (map_iter->first > p)
break;
++map_iter;
}
}
It may still make sense to use find() in some edge cases, specifically when myFavorites is significantly smaller than myMap, in which case a few calls to find() might be faster than iterating over (most of) the entire map.
How can I pack in a vector several different primitive data types as well as strings to examine the contents then?
(In Java, this went via Object [] objects = {1.0, "Hello", - 42, 'b'})
The task is as follows:
Given the following array: [3.0,42, "Monkey", 7.2, b]
This array is to be passed to a method that outputs the contents of the array on the console. If it is a string, each letter of the string should be added as an ASCII value in the same variable, and finally returned as an int on the console. With char exactly the same.
I know from today as I create a vector so with std::vector<double> numbers = {1.0,2.0}; How to write functions and how to access the indexes numbers[i]; as well as the length of the vector numbers.size().
How can I solve this problem now? Since I have unfortunately found no simple <- solution for the multiple types in a vector.
Thanks in advance :)
C++ does not do type erasure the same way that Java does. To create a heterogeneous container (which is the technical term for what you're trying to do) you'll need to make extensive use of std::any or std::variant, which are new classes introduced with C++17.
std::vector<std::any> values{1.0, "Hello", -42, 'b'};
for(auto & any : values) {
int * i;
if(val = std::any_cast<int>(&any)) std::cout << "int: " << *i << std::endl;
const char ** s;
if(s = std::any_cast<const char *>(&any)) std::cout << "string-literal: " << *s << std::endl;
double * d;
if(d = std::any_cast<double>(&any)) std::cout << "double: " << *d << std::endl;
char * c;
if(c = std::any_cast<char>(&any)) std::cout << "char: " << *c << std::endl;
}
Note how messy that code is. Not least of which because many people would desire "hello" to be stored as a std::string object, but this can't be done unless the user expressly designates it as such:
std::vector<std::any> values{1.0, std::string{"Hello"}, -42, 'b'};
At any rate, my personal opinion is that the use of std::variant would be a much better fit, as you can make it much clearer how the container is meant to be used, and you can avoid the dynamic allocations associated with std::any:
typedef std::variant<std::string, char, double, int> my_variant;
struct visitor {
void operator()(std::string const& v) const {
std::cout << "std::string: " << v<< std::endl;
}
void operator()(double const& v) const {
std::cout << "double: " << v << std::endl;
}
void operator()(int const& v) const {
std::cout << "int: " << v << std::endl;
}
void operator()(char const& v) const {
std::cout << "char: " << v << std::endl;
}
};
int main() {
std::vector<my_variant> values{1.0, "Hello", -42, 'b'};
for(my_variant & variant : values) {
std::visit(visitor{}, variant);
}
return 0;
}
We can even make the variant version a lot simpler with auto lambdas if we don't need to know the type:
typedef std::variant<std::string, char, double, int> my_variant;
int main() {
std::vector<my_variant> values{1.0, "Hello", -42, 'b'};
for(my_variant & variant : values) {
std::visit(
[](auto const& val) {std::cout << "Some unknown type: " << val << std::endl;},
variant
);
}
return 0;
}
I haven't run this through my compiler, but this should give a pretty good sense of how to accomplish this kind of task in C++.
If you don't have access to C++17, you can use boost.any and boost.variant, which I'm reasonably sure are both header-only libraries, and thus easy to import into your project.
My question is that of safety. I've searched cplusplus.com and cppreference.com and they seem to be lacking on iterator safety during std::move. Specifically: is it safe to call std::unordered_map::erase(iterator) with an iterator whose object has been moved? Sample code:
#include <unordered_map>
#include <string>
#include <vector>
#include <iostream>
#include <memory>
class A {
public:
A() : name("default ctored"), value(-1) {}
A(const std::string& name, int value) : name(name), value(value) { }
std::string name;
int value;
};
typedef std::shared_ptr<const A> ConstAPtr;
int main(int argc, char **argv) {
// containers keyed by shared_ptr are keyed by the raw pointer address
std::unordered_map<ConstAPtr, int> valued_objects;
for ( int i = 0; i < 10; ++i ) {
// creates 5 objects named "name 0", and 5 named "name 1"
std::string name("name ");
name += std::to_string(i % 2);
valued_objects[std::make_shared<A>(std::move(name), i)] = i * 5;
}
// Later somewhere else we need to transform the map to be keyed differently
// while retaining the values for each object
typedef std::pair<ConstAPtr, int> ObjValue;
std::unordered_map<std::string, std::vector<ObjValue> > named_objects;
std::cout << "moving..." << std::endl;
// No increment since we're using .erase() and don't want to skip objects.
for ( auto it = valued_objects.begin(); it != valued_objects.end(); ) {
std::cout << it->first->name << "\t" << it->first.value << "\t" << it->second << std::endl;
// Get named_vec.
std::vector<ObjValue>& v = named_objects[it->first->name];
// move object :: IS THIS SAFE??
v.push_back(std::move(*it));
// And then... is this also safe???
it = valued_objects.erase(it);
}
std::cout << "checking... " << named_objects.size() << std::endl;
for ( auto it = named_objects.begin(); it != named_objects.end(); ++it ) {
std::cout << it->first << " (" << it->second.size() << ")" << std::endl;
for ( auto pair : it->second ) {
std::cout << "\t" << pair.first->name << "\t" << pair.first->value << "\t" << pair.second << std::endl;
}
}
std::cout << "double check... " << valued_objects.size() << std::endl;
for ( auto it : valued_objects ) {
std::cout << it.first->name << " (" << it.second << ")" << std::endl;
}
return 0;
}
The reason I ask is that it strikes me that moving the pair from the unordered_map's iterator may (?) therefore *re*move the iterator's stored key value and therefore invalidate its hash; therefore any operations on it afterward could result in undefined behavior. Unless that's not so?
I do think it's worth noting that the above appears to successfully work as intended in GCC 4.8.2 so I'm looking to see if I missed documentation supporting or explicitly not supporting the behavior.
// move object :: IS THIS SAFE??
v.push_back(std::move(*it));
Yes, it is safe, because this doesn't actually modify the key. It cannot, because the key is const. The type of *it is std::pair<const ConstAPtr, int>. When it is moved, the first member (the const ConstAPtr) is not actually moved. It is converted to an r-value by std::move, and becomes const ConstAPtr&&. But that doesn't match the move constructor, which expects a non-const ConstAPtr&&. So the copy constructor is called instead.
For Windows 7 64-bit
So I set up my map
map<string, string> database;
database["user"] = "123";
It's part of the main function, but how can I print the contents of the map? And most importantly how can it be turned into a global variable so I can use it by other functions? I'm trying to put my printing map process in a different function than where the map was made.
You can iterate through map with following code:
for(auto it = database.begin(); it != database.end(); ++it) {
// it->first is your key
// it->second is value of particular key
std::cout << "Key: " << it->first << std::endl;
std::cout << "Value: " << it->second << std::endl;
// value can be reached as follows as well
std::cout << "Value: " << database[it->first] << std::endl;
}
Try this:
#include <map>
#include <iostream>
// this will be a global variable
map<string, string> database;
int main()
{
database["user"] = "123";
map<string, string>::iterator it;
for(it = database.begin(); it!= database.end(); it++)
{
pair<string, string> p = *it;
cout << "key=\"" << p.first << "\" value=\"" << p.second << "\"" << endl;
}
}
I'd advise to use C++11 features, like for_each, range based begin and end and lambda:
std::for_each(std::begin(database), std::end(database),
[&database](std::pair<std::string, std::string> p) {
std::cout << "Key : " << p.first << "\tValue : " << p.second << std::endl;
});
Second I'd avoid to make your map a global variable. There are reasons for global definitions, but for a container? (This maybe depends how big your project is, but I'd say let's get rid of any global variable, and if it is really needed put it inside a namespace)
Why not encapsulate your map into a class and provide functions to alter the content of your map, even your printing facility? If you want to make sure, that every user of your class shall have the same content of the map (translated this means the same instance), you can turn your class into a singleton.
If you have C++1 available (and as a sidenote to Stefan's answer: You don't actually need std::for_each or lambdas in C++11), iteration can be done using range based for:
for ( std::pair<std::string,std::string> const &p : database)
std::cout << "key=\"" << p.first << "\" value=\"" << p.second << "\"" << std::endl;
If you want to use it in other functions, think about several things instead of making the variable global:
Aggreate/incapsulate all functions using the database in a class
Pass the map object to your functions
I REALLY love lambdas and having the ability to use them in C++ is a pleasure. But, as I'm used to Haskell, where lambdas fit really well into the syntax, I'm struggling with how to use them in C++ without writing unreadable cluttered long code lines.
So, as an example, suppose I'd write this:
vector<double> foo(10,0.2);
for_each(foo.begin(), foo.end(), [](double x){ std::cout << x << " ";})
this is not so difficult to read, the lambda expression is pretty small. But if I have a two or three line long function inside that for_each, this could become a problem for my
code-reading-skills:
vector<double> foo(10,0.2);
randomNumberGenerator bar;
for_each(foo.begin(), foo.end(), [](double x){ std::cout << "hello!"; x+=bar()/(1+bar()); std::cout << x << " ";})
//sorry, I couldn't think of a less stupid example...
This line is starting to get annoyingly long and difficult to read for my taste...
What is your preferred code conventions for this case? Should I write:
for_each(foo.begin(), foo.end(),
[] (double x) {
std::cout << "hello!"
x += bar()/(1+bar());
std::cout << x << " ";
});
or something like it? I still think this syntax feels a bit unnatural and difficult to read... :(
I usually go for
for_each(foo.begin(), foo.end(), [](double x) {
std::cout << "hello!"
x += bar()/(1+bar());
std::cout << x << " ";
});
I've written some several hundred line lambdas.
If you prefer, you can name your lambda separately with auto:
auto const baz = [](double x)
{
std::cout << "hello!"
x += bar()/(1+bar());
std::cout << x << " ";
};
std::for_each(foo.begin(), foo.end(), baz);
Hmm...
for_each(foo.begin(), foo.end(),
[] (double x)
{
std::cout << "hello!"
x += bar()/(1+bar());
std::cout << x << " ";
});
for (auto x : foo)
{
std::cout << "hello!";
x += bar()/(1+bar());
std::cout << x << " ";
}
I like to look at lambdas as just another function declaration, and thus, follow the same conventions that I use for other functions, within reason:
// when lambdas are present, I break the enveloping method params
for_each(
foo.begin(),
foo.end(),
[] (double x)
// I also like to split the brackets, just like with any function
{
std::cout << "hello!"
x += bar()/(1+bar());
std::cout << x << " ";
}); // the closing parenthesis is left with the closing bracket
I'd say if the code for the lambda is more than one or perhaps two statements, it should be a separate named function.
Post mine
std::vector<int> a;
std::find_if(a.begin()
, a.end()
, [&](int i)
{
return i == 0;
});