i'm having a problem where i can't see what to do. I have to print map values with only STL loops, i can't use for loops while loops etc..
here's my map std::map<std::string, Borrowed*> map;
I'd rather not declare another function myself unless if it's really necessary to do that
Edit: I tried using for_each and copy function but if that's what you should use i don't see how you would use them
Just use std::for_each with a lambda that prints the element (using a map<string, int> for simplicitly, use your own code for printing Borrowed* elements).
#include <algorithm>
#include <iostream>
#include <iterator>
#include <map>
int main()
{
std::map<std::string, int> m = { { "bla", 1 }, { "yada", 2 } };
std::for_each(m.begin(), m.end(), [](auto const& elem) {
std::cout << "{ " << elem.first << ", " << elem.second << "}, ";
});
}
Live Example
Note this uses C++14 generalized lambdas (with auto to deduce the parameter type). In C++11 you'd have to explicitly write that out, and in C++98 you'd have to write your own function object to the lambda's work.
Assuming you mean STL algorithms:
Here is a std::for_each example (c++11):
#include <algorithm>
#include <iostream>
std::for_each(map.cbegin(), map.cend(),
[&](const std::pair<std::string, Borrowed*> &pair) {
std::cout << pair.first // std::string (key)
<< " " << pair.second->XXX // Borrowed* (value) or whatever you want to print here
<< "\n";
});
http://en.cppreference.com/w/cpp/algorithm/for_each
Related
I want to array "functions" by priority
E.g SetNumber1 is first
SetNumber2 is second
ReadNumbers is last
////////////////
priority_queue < ??? > Q
Q.push(ReadNumbers());
Q.push(SetNumber2());
Q.push(SetNumber1());
i want to exec in order to SetNumber1() , SetNumber2(), ReadNumbers()
Thanks.
and sorry about my english skils, I'am korean, i'm not good at english
std::priority_queue works with a compare function which can't work with the given functions. You need to define your own priorities as an enum and then you can put the pair of the prio and function in an std::multimap so all functions can be called according to their prio. You can put the pair also in a prio-q but then you still need a compare function that only works on the prio.
e.g.:
#include <iostream>
#include <map>
#include <functional>
enum class prio { HI, MID, LO };
int main()
{
std::multimap<prio, std::function<void()>> prio_mmap;
prio_mmap.insert(std::make_pair(prio::MID, []{ std::cout << "MID1\n"; }));
prio_mmap.insert(std::make_pair(prio::LO, []{ std::cout << "LO\n"; }));
prio_mmap.insert(std::make_pair(prio::HI, []{ std::cout << "HI\n"; }));
prio_mmap.insert(std::make_pair(prio::MID, []{ std::cout << "MID2\n"; }));
for (const auto& p: prio_mmap)
{
p.second();
}
}
I wanted a simple function that takes a collection of strings and appends them and returns one string which is each string item appended together. I thought std::accumulate was the way to go but interested to hear if this code could be improved.
Is there a simpler append type function that can be used here instead of the lambda?
Is this overly complicated and best achieved by some other code?
#include <string>
#include <vector>
#include <iostream>
#include <numeric>
std::string concatenate(std::vector<std::string> strings)
{
return std::accumulate(strings.begin(), strings.end(), std::string(""), [](std::string s1, std::string s2) { return s1 + s2; });
}
int main() {
std::vector<std::string> vec2{ "aaa","bbb","ccc","ddd","eee","fff" };
std::cout << concatenate(vec2) << std::endl;
}
Yes, you can omit the lambda entirely (or use std::plus<>{}).
Also the "" can be removed from std::string(""), or the whole third argument can be removed if you switch to std::reduce:
std::reduce(strings.begin(), strings.end());
Also concatenate should take the vector by a const reference, or even better a std::span<const std::string> (by value).
Also libfmt can be used for this:
fmt::format("{}", fmt::join(strings, ""));
It can be simplified with C++17 fold expression, there is no an intermediate or a temporary collection needed.
#include <string>
#include <iostream>
template<typename ...S>
std::string concatenate(S&&... strings) {
using namespace std::string_literals;
return (""s + ... + strings);
}
int main() {
std::cout << concatenate("aaa","bbb","ccc","ddd","eee","fff") << std::endl;
}
I noticed that I can seemingly get the same logic(copy elements matching some predicate into vector) both using ranges::copy_if and also using vector constructor taking 2 iterators(by providing it with filter_view .begin() and .end()).
#include <algorithm>
#include <iostream>
#include <ranges>
#include <vector>
#include <utility>
#include <fmt/ranges.h>
const std::vector<int> vals{1,2,3,47,8472};
const auto filter_pred = [](const int i){return i%2==0;};
void fna(){
std::vector<int> result;
std::ranges::copy_if(vals, std::back_inserter(result), filter_pred);
std::cout << fmt::format("{}", result) << std::endl;
}
void fn1(){
auto filtered = vals | std::views::filter(filter_pred);
std::vector<int> result {filtered.begin(), filtered.end()};
std::cout << fmt::format("{}", result) << std::endl;
}
std::vector<int> fna_val(){
std::vector<int> result;
std::ranges::copy_if(vals, std::back_inserter(result), filter_pred);
return result;
}
std::vector<int> fn1_val(){
auto filtered = vals | std::views::filter(filter_pred);
return {filtered.begin(), filtered.end()};
}
int main(){
fna();
fn1();
std::cout << fmt::format("{}", fna_val()) << std::endl;
std::cout << fmt::format("{}", fn1_val()) << std::endl;
}
Is there a reason to prefer one over other?
What I can think of:
it is unlikely that either is more efficient, since I doubt that any real optimizations can be done since because _if in copy_if means destination size is unknown.
compile speed: copy_if could be faster to compile since it does not require <ranges> header, but did not benchmark
const all the things: copy_if requires mutable destination container, range construction does not
verbosity: when return type of function is known we do not need to spell out the std::vector in body, {} works. Would be nice if vector understood ranges so we would not have to use .begin() .end(), but it does not.
Trying to learn C++ coming from Python, and in python a set can have multiple types. How do I do this in C++? I'm specifically trying to have a set with both integers and strings. For example:
#include <set>
#include <string>
using namespace std;
int main() {
set<int, string> s;
s.insert(1);
s.insert("string");
}
Having multiple types of elements in a container is called a heterogenous container.
C++ supports this from C++17 using std::any which can hold any type, or as EOF said using std::variant when you want to define the set of possible types yourself.
Here is a demo of std::any using std::any_cast:
#include <any>
#include <iostream>
#include <list>
#include <map>
#include <set>
int main()
{
std::list<std::any> any_list;
int myInt = 1;
std::string myString("I'm a string");
using MapType = std::map<std::list<int>, std::string>;
MapType myMap;
struct CustomType {
void* pointer;
};
any_list.emplace_back(std::any());
any_list.emplace_back(myInt);
any_list.emplace_back(myString);
any_list.emplace_back(myMap);
any_list.emplace_back(CustomType());
// To show the awesome power of std::any we add
// the list as an element of itself:
any_list.emplace_back(any_list);
for(auto& element: any_list) {
if(!element.has_value()) {
std::cout << "Element does not hold a value" << std::endl;
continue;
}
if (int* someInt = std::any_cast<int>(&element)) {
std::cout << "Element is int: " << *someInt << '\n';
} else if (std::string* s = std::any_cast<std::string>(&element)) {
std::cout << "Element is a std::string: " << *s << '\n';
} else if (std::any_cast<MapType>(&element)) {
std::cout << "Element is of type MapType\n";
} else if (std::any_cast<CustomType>(&element)) {
std::cout << "Element is of type CustomType\n";
} else {
std::cout << "Element is of unknown but very powerful type\n";
}
}
}
This yields output:
Element does not hold a value
Element is int: 1
Element is a std::string: I'm a string
Element is of type MapType
Element is of type CustomType
Element is of unknown but very powerful type
The pre-C++17 method of doing this is obviously a struct with manual type info and void*.
Note that I used std::list instead of std::set because std::any does not have operator< defined by default. This could be solved by defining your own comparison predicate.
My personal opinion is that usually when you think you want to use a heterogenous container it's worth re-evaluating your design and stick to normal homogenous containers, but it's there if you need it :-)
Is there a more straight-forward way to do this?
for_each(v_Numbers.begin(), v_Numbers.end(), bind1st(operator<<, cout));
Without an explicit for loop, if possible.
EDIT:
How to do this for std::cin with a std::vector if possible? (How to read n elements only)?
You could achieve this using std::copy into a std::ostream_iterator:
std::vector<int> v_Numbers; // suppose this is the type
// put numbers in
std::copy(v_Numbers.begin(), v_Numbers.end(),
std::ostream_iterator<int>(std::cout));
It would be even nicer if you add some suffix:
std::copy(v_Numbers.begin(), v_Numbers.end(),
std::ostream_iterator<int>(std::cout, "\n"));
This assumes that your container is a vector<int>, so you will have to replace that part with the appropriate type.
Edit regarding reading input:
Conversely, you can copy from a range of std::istream_iterator into a vector using std::back_inserter:
std::vector<int> v_Numbers;
std::copy(std::istream_iterator<int>(std::cin), std::istream_iterator<int>(),
std::back_inserter(v_Numbers));
If you want to read n elements only, look at this question.
Another option — Boost.Lambda.
for_each(v.begin(), v.end(), cout << boost::lambda::_1);
Yep, but you must use std::copy algorithm:
#include <iostream>
#include <iterator>
#include <vector>
int main()
{
std::vector<int> a;
// fill a...
std::copy(a.begin(), a.end(), std::ostream_iterator<int>(std::cout));
}
yup, using lambda expression (C++ 11) we can inline printing of each element of a STL container to cout.
#include <iostream> // cout
#include <vector> // vector
#include <algorithm> // for_each
#include <iterator> // istream_iterator
using namespace std;
int main()
{
std::vector<int> v(10,2);
std::for_each(v.begin(), v.end(), [](int i)->void {std::cout << i <<endl;});
return 0;
}
For reading "n" values from cin to vector,
int main()
{
std::vector<int> v;
int elementsToRead;
cin>>elementsToRead; // Number of elements to copy
// Reading from istream
std::istream_iterator<int> ii2(std::cin);
std::copy_n(ii2, elementsToRead, std::back_inserter(v));
// printing updated vector
std::for_each(v.begin(), v.end(), [](int i)->void {cout << i <<endl;});
return 0;
}
(or) by using Lambda expression
std::for_each(std::istream_iterator<int>(cin),std::istream_iterator<int>(),[&v](int i)->void { v.push_back(i);});
To know more about Lambda expression # What is a lambda expression in C++11?
Not always appropriate in corporate code, but for the sake of enumerating options - if you really find other for_each / std::copy etc. solutions too verbose, you could write:
std::ostream& operator(std::ostream& os, const std::vector<My_Type>& v)
{
// pick one of the other implementations for here...
std::copy(std::istream_iterator<My_Type>(os), std::istream_iterator<My_Type>(),
std::back_inserter(v_Numbers));
}
It's much nicer if you're well-mannered (;-p) enough to only overload your specific instantiation of vector (which requires My_Type be more than a typedef to say int, though it's not hard to create a templated class to create new types wrapping an arbitrary type). Otherwise, if someone else does the same elsewhere in your translation unit, the streaming could become ambiguous.
I know the copy with the iterator is the optimal solution, but just to answer with for_each.
You could do:
#include <vector>
#include <algorithm>
#include <locale>
int main() {
using namespace std;
locale::global(locale(""));
wcout::imbue(locale());
vector<int> vec{1000,2000,3000,4000,5000};
for_each(vec.begin(), vec.end(), [](auto &x){wcout << x << endl;});
return 0;
}
But, for me, it's REALLY much more readable the simple for ...
#include <vector>
#include <locale>
int main() {
using namespace std;
locale::global(locale(""));
wcout::imbue(locale());
vector<int> vec{1000,2000,3000,4000,5000};
for(auto &v: vec) {
wcout << v << endl;
}
return 0;
}