list(vector) definition with array - c++

I have Class Email,
there is parameter "bcc" in her constructor.
Its actually list of emails for copies.
There is no fixed number of these emails and later i have to have possibility to extend this list.
//constructor prototype
Email::Email(vector<string> bcc)
So i want to use type vector or list for that and function push_back().
How can i make a new instance with bcc emails?
I need actually declaration with definition for my list.
I've found this definition with iterator for integer type:
int myints[] = {16,2,77,29};
Email myEmail(vector<int> (myints, myints + sizeof(myints) / sizeof(int) ));
, but its not very user friend and i need it with strings.
Is there something like this?
Email myEmail(vector<string> ("first","second","third"));

Apart from C++0x list-initialization, there is the Boost.Assign library which should do similar things.

If you have C++0x, you can do vector { "first", "second", "third" }. Else, you will have to create a new vector in scope somewhere and manually push on each that you want, then construct.
Also, you should really take that vector by reference, it's really quite large.
You should use a std::vector unless you know that you will need to insert items into the middle, not on the end.

If you're not using C++0x then you have no access to initialisers. Could you add a constructor that takes any old iterator, viz:
#include <vector>
#include <list>
#include <iostream>
struct Email
{
typedef std::vector<std::string> BccType;
BccType m_bcc;
template <typename T>
Email(const T& iter, const T& end)
:m_bcc(iter, end)
{
}
// Purely here for illustrative purposes...
void display()
{
std::cerr << m_bcc.size() << " addresses..." << std::endl;
for (BccType::iterator iter = m_bcc.begin(), iterEnd = m_bcc.end(); iter != iterEnd; ++iter)
{
std::cerr << *iter << std::endl;
}
}
};
int main(int, char*[])
{
// Plain old char* array...
const char* bcc[] = {"Jeff", "Joel", "Larry", "Brin"};
const size_t count = sizeof bcc / sizeof bcc[0];
Email email(&bcc[0], bcc + count);
email.display();
// STL container variation...
std::list<std::string> names;
names.push_back("Bill");
names.push_back("Steve");
Email reply(names.begin(), names.end());
reply.display();
return 0;
}
There is, of course, no reason why you can't have a ctor that takes const BccType& (typedefed for brevity and maintainability) additionally. Note that I suggest passing this by reference to save copying the std::vector twice.

Related

C++ Handle Dynamic mapping between member variable name and its value

There is a class say Person which has member variables name, email, mobile, gender.
Now, we are getting this information in an array.
std::vector<std::string> a[] = {"XYZ", "xyz#mail.com", "1234567890", "Male"};
Person p;
Now, instead of writing it like:
p.name = a[0]; p.email = a[1]....
I want something like this for dynamic allocation as well as for reducing code lines:-
std::vector<std::string> b[] = {"name", "email", "mobile", "gender"};
int len = a.size();
for (int i=0; i < len ; i++)
{
set_value(p, b[i], a[i]);
}
How to write a function like set_value, or is there any way to do something like this in c++ ?
Right now in above example we have a vector size of 4, but it can be in size of 10 or 50 or more also. In that case if we don't have the way of setting the values dynamically then we might have to write same number of lines for setting every member variable .. .?
I think one of the solutions in which you are talking about is to implement all the fields of the Person class as a map<K, V>, which will store all of yours properties. In this case you will be able to refer to the value by the key of a map.
I would not recommend this solution for you. You can think of set_value function as a way in which the names from array a should refer to the name of the properties or rather how does those names should be linked to the functions which could invoke a proper property-right set method.
If those setting functions you are interested in use the same base type as a parameter, you could create map of strings and function pointers.
#include <map>
#include <vector>
#include <string>
#include <iostream>
using namespace std;
class Person{
std::map<std::string, std::string> _properties;
public:
Person() = default;
~Person() = default;
void set_values(vector<string> & fields, vector<string> & values){
if(fields.size() != values.size()) return;
for(int i = 0; i < fields.size(); ++i){
_properties.insert_or_assign(fields[i], values[i]);
}
}
void print(){
for (auto const &it : _properties)
std::cout << it.first << " => " << it.second << '\n';
}
};
int main(){
Person p;
vector<string> fields = {"email", "name"};
vector<string> values = {"a#b.com", "Andrew"};
p.set_values(fields, values);
p.print();
vector<string> fields2 = {"name"};
vector<string> values2 = {"Tom"};
p.set_values(fields2, values2);
p.print();
return 0;
}
This minimal working example shows what you want to get and it has a lot of constraints, such as it assumes that all of the values are stored as a std::string which can not be a good in every case. It produces a following output after applying the first set of fields and values:
email => a#b.com
name => Andrew
After the second one, the email stays the same but name is updated as follows:
email => a#b.com
name => Tom
I've compiled it using g++ version 7.1 using using following command:
g++ --std=c++1z main.cpp on my Fedora 26.
Well, there are no easy way to set a variable by name... There are library that allows to do something like that (for ex. boost fusion) but in practice, you could also write a simple function if you have only a few functions to write on a few classes.
One simple possibility assuming you want to reuse the code that fill a object:
void set_values_of(Person &p, const std::vector<std::string> &data)
{
assert(data.size() == 4); // put whatever error handling you want...
p.name = data[0];
p.email = data[1];
p.mobile = data[2];
p.gender = data[3];
}
And if you prefer, you might change second argument for another source (for ex. a stream or one line a string). At that point, it really depends on your application.
If your prefer immuable objects, you might also consider having a factory free function:
Person create_from(const std::vector<std::string> &data) { ... }

C++ Iterator for std::set or std::vector

Let's say I have this:
struct HoldStuff {
std::vector<StuffItem> items;
std::set<StuffItem, StuffItemComparator> sorted_items;
}
Now, during a refactor, I may have stuff in items or I may have it in sorted_items, but regardless I want to do the same thing with each item. I want to do something like this:
HoldStuff holder; // assume it was filled earlier
auto iter = holder.items.empty() ? holder.sorted_items.begin() :
holder.items.begin();
auto iter_end = holder.items.empty() ? holder.sorted_items.end() :
holder.items.end();
for (; iter != iter_end; ++iter) {
auto& item = *iter;
// Do stuff
}
When I go to compile this, I get errors complaining about incompatible operand types. Surely this is possible, no?
You have two options:
use type-erasure to get a runtime polymorphism on the iterator (any_range or any_iterator)
delegate do_stuff to a function template that takes any kind of iterator
Here is an illustration with code:
#include <vector>
#include <set>
#include <iostream>
#include <boost/range/any_range.hpp>
template<typename Iterator>
void do_stuff(Iterator begin, Iterator end) {}
int main()
{
std::vector<int> items;
std::set<int> sorted_items;
// first option
typedef boost::any_range<int, boost::forward_traversal_tag, int&, std::ptrdiff_t> my_any_range;
my_any_range r;
if(items.empty())
r = my_any_range(sorted_items);
else
r = my_any_range(items);
for (auto& x : r) {
std::cout << x << " ";
}
// second option
// this could also be a lambda and std::for_each
if(items.empty())
do_stuff(sorted_items.begin(), sorted_items.end());
else
do_stuff(items.begin(), items.end());
return 0;
}
Both sides of the ternary operator need to have the same type. In your case, they are different - std::vector<>::iterator and std::set<> iterator. A suitable solution seems to be some sort of a an iterator wrapper, which returns one or another depending on the initial condition.
The errors are correct: auto keyword works during compilation. In an easy way, it just deduces the type of assignment and uses this real type. But decision if it's vector's iterator or set's is made in runtime. So type can not be deduced.
As SergeyA said, I'm wrong here, compiler fail on ?: operator, before auto. But the reason is still the same - it has no idea which type to use for the result.
You should probably use some more generic iterator type + polymorphism, or you can make this function parameterized on type , where T is an iterator type. I would prefer to do it this way:
template<class T> do_stuff(T &c) { for (auto &el : c) { /*Whatever*/ } }
...
if (!items.empty()) {
do_stuff(items);
} else if (!sorted_items.empty()) {
do_stuff(sorted_items);
}
P.S.: It's a conception, I didn't test the code.
auto means the compiler will deduce the type of what follows, at compilation time.
The return type of the ternary conditional operator in this case is what follows the question mark, so it is std::set<StuffItem, StuffItemComparator>::iterator and the compiler tries to cast what follows the column (std::vector<StuffItem>::iterator) to this incompatible type, hence the compiler error.
What you can do is make your item processing code generic, like so:
auto doStuff = [] (StuffItem& item) {
// do stuff with item...
};
if( holder.items.size() )
for_each( holder.items.begin(), holder.items.end(), doStuff );
else if( holder.sorted_items.size() )
for_each( holder.sorted_items.begin(), holder.sorted_items.end(), doStuff );

Get Element Position within std::vector

How do I get the position of an element inside a vector, where the elements are classes. Is there a way of doing this?
Example code:
class Object
{
public:
void Destroy()
{
// run some code to get remove self from vector
}
}
In main.cpp:
std::vector<Object> objects;
objects.push_back( <some instances of Object> );
// Some more code pushing back some more stuff
int n = 20;
objects.at(n).Destroy(); // Assuming I pushed back 20 items or more
So I guess I want to be able to write a method or something which is a member of the class which will return the location of itself inside the vector... Is this possible?
EDIT:
Due to confusion, I should explain better.
void Destroy(std::vector<Object>& container){
container.erase( ?...? );
}
The problem is, how can I find the number to do the erasing...? Apparently this isn't possible... I thought it might not be...
You can use std::find to find elements in vector (providing you implement a comparison operator (==) for Object. However, 2 big concerns:
If you need to find elements in a container then you will ger much better performance with using an ordered container such as std::map or std::set (find operations in O(log(N)) vs O(N)
Object should not be the one responsible of removing itself from the container. Object shouldn't know or be concerned with where it is, as that breaks encapsulation. Instead, the owner of the container should concern itself ith such tasks.
The object can erase itself thusly:
void Destroy(std::vector<Object>& container);
{
container.erase(container.begin() + (this - &container[0]));
}
This will work as you expect, but it strikes me as exceptionally bad design. Members should not have knowledge of their containers. They should exist (from their own perspective) in an unidentifiable limbo. Creation and destruction should be left to their creator.
Objects in a vector don't automatically know where they are in the vector.
You could supply each object with that information, but much easier: remove the object from the vector. Its destructor is then run automatically.
Then the objects can be used also in other containers.
Example:
#include <algorithm>
#include <iostream>
#include <vector>
class object_t
{
private:
int id_;
public:
int id() const { return id_; }
~object_t() {}
explicit object_t( int const id ): id_( id ) {}
};
int main()
{
using namespace std;
vector<object_t> objects;
for( int i = 0; i <= 33; ++i )
{
objects.emplace_back( i );
}
int const n = 20;
objects.erase( objects.begin() + n );
for( auto const& o : objects )
{
cout << o.id() << ' ';
}
cout << endl;
}
If you need to destroy the n'th item in a vector then the easiest way is to get an iterator from the beginning using std::begin() and call std::advance() to advance how ever many places you want, so something like:
std::vector<Object> objects;
const size_t n = 20;
auto erase_iter = std::advance(std::begin(objects), n);
objects.erase(erase_iter);
If you want to find the index of an item in a vector then use std::find to get the iterator and call std::distance from the beginning.
So something like:
Object object_to_find;
std::vector<Object> objects;
auto object_iter = std::find(std::begin(objects), std::end(objects), object_to_find);
const size_t n = std::distance(std::begin(objects), object_iter);
This does mean that you need to implement an equality operator for your object. Or you could try something like:
auto object_iter = std::find(std::begin(objects), std::end(objects),
[&object_to_find](const Object& object) -> bool { return &object_to_find == &object; });
Although for this to work the object_to_find needs to be the one from the actual list as it is just comparing addresses.

How can I return a copy of a vector containing elements not in a set?

Suppose I have the following two data structures:
std::vector<int> all_items;
std::set<int> bad_items;
The all_items vector contains all known items and the bad_items vector contains a list of bad items. These two data structures are populated entirely independent of one another.
What's the proper way to write a method that will return a std::vector<int> contain all elements of all_items not in bad_items?
Currently, I have a clunky solution that I think can be done more concisely. My understanding of STL function adapters is lacking. Hence the question. My current solution is:
struct is_item_bad {
std::set<int> const* bad_items;
bool operator() (int const i) const {
return bad_items.count(i) > 0;
}
};
std::vector<int> items() const {
is_item_bad iib = { &bad_items; };
std::vector<int> good_items(all_items.size());
std::remove_copy_if(all_items.begin(), all_items.end(),
good_items.begin(), is_item_bad);
return good_items;
}
Assume all_items, bad_items, is_item_bad and items() are all a part of some containing class. Is there a way to write them items() getter such that:
It doesn't need temporary variables in the method?
It doesn't need the custom functor, struct is_item_bad?
I had hoped to just use the count method on std::set as a functor, but I haven't been able to divine the right way to express that w/ the remove_copy_if algorithm.
EDIT: Fixed the logic error in items(). The actual code didn't have the problem, it was a transcription error.
EDIT: I have accepted a solution that doesn't use std::set_difference since it is more general and will work even if the std::vector isn't sorted. I chose to use the C++0x lambda expression syntax in my code. My final items() method looks like this:
std::vector<int> items() const {
std::vector<int> good_items;
good_items.reserve(all_items.size());
std::remove_copy_if(all_items.begin(), all_items.end(),
std::back_inserter(good_items),
[&bad_items] (int const i) {
return bad_items.count(i) == 1;
});
}
On a vector of about 8 million items the above method runs in 3.1s. I bench marked the std::set_difference approach and it ran in approximately 2.1s. Thanks to everyone who supplied great answers.
As jeffamaphone suggested, if you can sort any input vectors, you can use std::set_difference which is efficient and less code:
#include <algorithm>
#include <set>
#include <vector>
std::vector<int>
get_good_items( std::vector<int> const & all_items,
std::set<int> const & bad_items )
{
std::vector<int> good_items;
// Assumes all_items is sorted.
std::set_difference( all_items.begin(),
all_items.end(),
bad_items.begin(),
bad_items.end(),
std::back_inserter( good_items ) );
return good_items;
}
Since your function is going to return a vector, you will have to make a new vector (i.e. copy elements) in any case. In which case, std::remove_copy_if is fine, but you should use it correctly:
#include <iostream>
#include <vector>
#include <set>
#include <iterator>
#include <algorithm>
#include <functional>
std::vector<int> filter(const std::vector<int>& all, const std::set<int>& bad)
{
std::vector<int> result;
remove_copy_if(all.begin(), all.end(), back_inserter(result),
[&bad](int i){return bad.count(i)==1;});
return result;
}
int main()
{
std::vector<int> all_items = {4,5,2,3,4,8,7,56,4,2,2,2,3};
std::set<int> bad_items = {2,8,4};
std::vector<int> filtered_items = filter(all_items, bad_items);
copy(filtered_items.begin(), filtered_items.end(), std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
}
To do this in C++98, I guess you could use mem_fun_ref and bind1st to turn set::count into a functor in-line, but there are issues with that (which resulted in deprecation of bind1st in C++0x) which means depending on your compiler, you might end up using std::tr1::bind anyway:
remove_copy_if(all.begin(), all.end(), back_inserter(result),
bind(&std::set<int>::count, bad, std::tr1::placeholders::_1)); // or std::placeholders in C++0x
and in any case, an explicit function object would be more readable, I think:
struct IsMemberOf {
const std::set<int>& bad;
IsMemberOf(const std::set<int>& b) : bad(b) {}
bool operator()(int i) const { return bad.count(i)==1;}
};
std::vector<int> filter(const std::vector<int>& all, const std::set<int>& bad)
{
std::vector<int> result;
remove_copy_if(all.begin(), all.end(), back_inserter(result), IsMemberOf(bad));
return result;
}
At the risk of appearing archaic:
std::set<int> badItems;
std::vector<int> items;
std::vector<int> goodItems;
for ( std::vector<int>::iterator iter = items.begin();
iter != items.end();
++iter)
{
int& item = *iter;
if ( badItems.find(item) == badItems.end() )
{
goodItems.push_back(item);
}
}
std::remove_copy_if returns an iterator to the target collection. In this case, it would return good_items.end() (or something similar). good_items goes out of scope at the end of the method, so this would cause some memory errors. You should return good_items or pass in a new vector<int> by reference and then clear, resize, and populate it. This would get rid of the temporary variable.
I believe you have to define the custom functor because the method depends on the object bad_items which you couldn't specify without it getting hackey AFAIK.

How to iterate over a std::map full of strings in C++

I have the following issue related to iterating over an associative array of strings defined using std::map.
-- snip --
class something
{
//...
private:
std::map<std::string, std::string> table;
//...
}
In the constructor I populate table with pairs of string keys associated to string data. Somewhere else I have a method toString that returns a string object that contains all the keys and associated data contained in the table object(as key=data format).
std::string something::toString()
{
std::map<std::string, std::string>::iterator iter;
std::string* strToReturn = new std::string("");
for (iter = table.begin(); iter != table.end(); iter++) {
strToReturn->append(iter->first());
strToReturn->append('=');
strToRetunr->append(iter->second());
//....
}
//...
}
When I'm trying to compile I get the following error:
error: "error: no match for call to ‘(std::basic_string<char,
std::char_traits<char>, std::allocator<char> >) ()’".
Could somebody explain to me what is missing, what I'm doing wrong?
I only found some discussion about a similar issue in the case of hash_map where the user has to define a hashing function to be able to use hash_map with std::string objects. Could be something similar also in my case?
Your main problem is that you are calling a method called first() in the iterator. What you are meant to do is use the property called first:
...append(iter->first) rather than ...append(iter->first())
As a matter of style, you shouldn't be using new to create that string.
std::string something::toString()
{
std::map<std::string, std::string>::iterator iter;
std::string strToReturn; //This is no longer on the heap
for (iter = table.begin(); iter != table.end(); ++iter) {
strToReturn.append(iter->first); //Not a method call
strToReturn.append("=");
strToReturn.append(iter->second);
//....
// Make sure you don't modify table here or the iterators will not work as you expect
}
//...
return strToReturn;
}
edit: facildelembrar pointed out (in the comments) that in modern C++ you can now rewrite the loop
for (auto& item: table) {
...
}
Don't write a toString() method. This is not Java. Implement the stream operator for your class.
Prefer using the standard algorithms over writing your own loop. In this situation, std::for_each() provides a nice interface to what you want to do.
If you must use a loop, but don't intend to change the data, prefer const_iterator over iterator. That way, if you accidently try and change the values, the compiler will warn you.
Then:
std::ostream& operator<<(std::ostream& str,something const& data)
{
data.print(str)
return str;
}
void something::print(std::ostream& str) const
{
std::for_each(table.begin(),table.end(),PrintData(str));
}
Then when you want to print it, just stream the object:
int main()
{
something bob;
std::cout << bob;
}
If you actually need a string representation of the object, you can then use lexical_cast.
int main()
{
something bob;
std::string rope = boost::lexical_cast<std::string>(bob);
}
The details that need to be filled in.
class somthing
{
typedef std::map<std::string,std::string> DataMap;
struct PrintData
{
PrintData(std::ostream& str): m_str(str) {}
void operator()(DataMap::value_type const& data) const
{
m_str << data.first << "=" << data.second << "\n";
}
private: std::ostream& m_str;
};
DataMap table;
public:
void something::print(std::ostream& str);
};
Change your append calls to say
...append(iter->first)
and
... append(iter->second)
Additionally, the line
std::string* strToReturn = new std::string("");
allocates a string on the heap. If you intend to actually return a pointer to this dynamically allocated string, the return should be changed to std::string*.
Alternatively, if you don't want to worry about managing that object on the heap, change the local declaration to
std::string strToReturn("");
and change the 'append' calls to use reference syntax...
strToReturn.append(...)
instead of
strToReturn->append(...)
Be aware that this will construct the string on the stack, then copy it into the return variable. This has performance implications.
Note that the result of dereferencing an std::map::iterator is an std::pair. The values of first and second are not functions, they are variables.
Change:
iter->first()
to
iter->first
Ditto with iter->second.
iter->first and iter->second are variables, you are attempting to call them as methods.
Use:
std::map<std::string, std::string>::const_iterator
instead:
std::map<std::string, std::string>::iterator
Another worthy optimization is the c_str ( ) member of the STL string classes, which returns an immutable null terminated string that can be passed around as a LPCTSTR, e. g., to a custom function that expects a LPCTSTR. Although I haven't traced through the destructor to confirm it, I suspect that the string class looks after the memory in which it creates the copy.
In c++11 you can use:
for ( auto iter : table ) {
key=iter->first;
value=iter->second;
}