I am trying to learn the standard library in C++ and I'm trying to run my code, but I can't succeed. What have I forgotten and what do I need to add in my class "Class" to make the program run as it should?
#include <iostream>
#include <vector>
#include <list>
#include <algorithm>
#include <iterator>
using namespace std;
class Class {
public:
Class (int ii, double dd ) : ival(ii) { dval = new double; *dval = dd; }
~Class() { delete dval; }
private:
int ival;
double *dval;
};
int main()
{
vector<Class> vec;
list<Class> list;
vec.push_back( Class(1, 2.2) );
vec.push_back( Class(2, 4.3) );
vec.push_back( Class(3, 5.7) );
ostream_iterator<const Class> classout(cout,"\n");
copy( vec.begin(), vec.end(), classout );
}
I'm basically trying to understand and use the copy-algorithm:
template
OutputIterator copy ( InputIterator first, InputIterator last,
OutputIterator result )
{
while (first!=last) *result++ = *first++;
return result;
}
std::ostream_iterator uses the insertion operator << to insert objects into the output stream. You must provide such an operator. An example implementation using a member function:
class Class {
public:
Class (int ii, double dd ) : ival(ii) { dval = new double; *dval = dd; }
~Class() { delete dval; }
void print(std::ostream &stream) const {
stream << ival << ' ' << *dval;
}
private:
int ival;
double *dval;
};
std::ostream& operator<< (std::ostream &stream, const Class &arg) {
arg.print(stream);
return stream;
}
As an alternative, you could also implement it by making it a friend and not creating a member function.
Your code has several problem. The first, which should lead to a compile error is, that your class doesn't declare a << operator for streamout, meaning that it can't be printed to a stream using a ostream_iterator. To fix that, you need to add such an operator to your class, e.g.:
class Class {
public:
Class (int ii, double dd ) : ival(ii) { dval = new double; *dval = dd; }
~Class() { delete dval; }
friend std::ostream& operator<<(std::ostream& os, const Class& c)
{
return os<<c.ival<<": "<<*c.dval;//or whatever you want your output to look like
}
private:
int ival;
double *dval;
};
However your code still contains one serious problem: A violation of the rule of three (or five/whatever if you are on c++11). Your class declares a custom destructor, but neither a custom copy constructor nor a custom assignment operator. This means that when you copy an instance of your class (such as putting it into a vector, both objects will contain the same pointer, leading to a runtime error due to double free on the destruction of the second object. To fix that you either need to declare those operations yourself or (even better) don't do resource management yourself, but use smart pointers instead (c++11 std::unique_ptr or std::shared_ptr, std::tr1::shared_ptr or a pointer from boost for pree C++11 code).
Related
The problem in question is related to the question and discussion found in this SO thread.
The problem is essentially as follows, I have an abstract class called players. Then I have two classes attackers and defenders. Now, I would like to have an unordered container (map, set, etc.) containing all players. For that I need a hash function (which is not the issue as both attackers and defenders have names) and an equality function. The latter is the problem. As discussed in the linked SO thread, it seems to be bad practice to inherit operator== and I can see why.
I now wonder what the idiomatic solution to my problem is. Is it to just have two containers? One for players and one for attackers? Are there other solutions?
Edit:
Yes, I am talking about unordered_* containers. I am aware that I would need to store pointers in the containers rather than objects themselves. For example, I'd have a container std::unordered_set<std::shared_ptr<players>> all_players.
When you instantiate your map, you can specify a comparator:
template< class InputIt >
map( InputIt first, InputIt last,
const Compare& comp = Compare(), /// << this here
const Allocator& alloc = Allocator() );
Reference: https://en.cppreference.com/w/cpp/container/map/map
Then, you don't need to define the equality operator. In any case, in order to store polymorphic objects in a map, you'll need to store pointers.
So, you would need a comparator anyway, in order to compare the objects, not the pointer values.
In order to store multiple different types in the same container, you have to take advantage of polymorphism.
Polymorphism requires you to use pointers to objects instead of actual objects. That's because C/C++ doesn't allow you to make arrays of multiple different types. The best way to do that in modern C++ is to use std::unique_ptr or std::shared_ptr from #include <memory>
To make a polymorphic container you'll need the following:
A common base struct/class that all of your types inherit from.
Some way to interface with subtype-specific methods/members.
This can be a virtual method in the base object, a member of the base object, or you can also use typeid to figure out what type something is at runtime.
#include <iostream>
#include <vector>
#include <memory>
#include <typeinfo>
struct base {
virtual ~base() = default;
virtual int GetValue() const = 0;
};
struct A : base {
int a;
A(const int v) : a{ v } {}
int GetValue() const override { return a; }
void doSomething() const { std::cout << "Hello World!"; }
};
struct B : base {
int b;
int mult;
B(const int v, const int mult) : b{ v }, mult{ mult } {}
int GetValue() const override { return b * mult; }
void doSomethingElse() const { std::cout << "!dlroW olleH"; }
};
int main()
{
std::vector<std::unique_ptr<base>> vec;
vec.emplace_back(std::make_unique<A>(5)); //< insert an object of type A
vec.emplace_back(std::make_unique<B>(8, 2)); //< insert an object of type B
for (const auto& it : vec) {
std::cout << it->GetValue() << '\t';
if (typeid(*it.get()) == typeid(A)) {
((A*)it.get())->doSomething();
}
else if (typeid(*it.get()) == typeid(B)) {
((B*)it.get())->doSomethingElse();
}
std::cout << std::endl;
}
}
Outputs:
5 Hello World!
16 !dlroW olleH
You need a hash function-object that looks through your pointers. The base class can have non-virtual implementations, or equivalently you can have the hasher inspect the public members.
class players {
public:
size_t hash() const;
friend bool operator==(const player & lhs, const player & rhs);
};
using std::unique_ptr<players> players_ptr;
struct players_hash {
size_t operator()(const players_ptr & ptr) { return ptr->hash(); }
};
struct players_equal {
bool operator()(const players_ptr & lhs, const players_ptr & rhs) { return *lhs == *rhs; }
};
std::unordered_set<players_ptr, players_hash, players_equal> all_players;
I have a class that must return a constant view of some pointers to the upper layers of software.
Internally, the pointers must be non-const, because the class will need to manipulate the objects internally.
I don't see any option for providing this const view of the pointers to a higher level client, without making a copy of all the pointers. This seems wasteful. What if I was managing millions of objects?
Is there a better way?
Here is some example code:
#include <vector>
#include <iostream>
class example {
public:
example() {
bytePtrs_.push_back(new char);
*bytePtrs_[0] = '$';
}
// I want to do this, but compiler will not allow
// error: could not convert ‘((example*)this)->example::bytePtrs_’ from ‘std::vector<char*>’ to ‘std::vector<const char*>’
std::vector<const char*> getPtrs() {
return bytePtrs_;
}
// Must make wasteful copy
std::vector<const char*> getPtrs() {
std::vector<const char*> ret;
for (auto &ptr : bytePtrs_)
ret.push_back(ptr);
return ret;
}
private:
std::vector<char*> bytePtrs_;
};
int main() {
example e;
std::vector<const char*> bytePtrs = e.getPtrs();
std::cout << bytePtrs[0] << std::endl;
}
You can do this using std::experimental::propagate_const.
That will forward the constness of the pointer onto the pointed-to object.
#include <experimental/propagate_const>
class example {
public:
// using vector = std::vector<char*>>;
using vector = std::vector<std::experimental::propagate_const<char*>>;
example() {
bytePtrs.push_back(new char);
*bytePtrs[0] = '$';
}
vector const& getPtrs() const {
return bytePtrs;
}
private:
vector bytePtrs;
};
int main()
{
example e;
example::vector const& bytePtrs = e.getPtrs();
// dereference this or add a null terminator
std::cout << *bytePtrs[0] << std::endl; // fine and dandy
*bytePtrs[0] = 'x'; // compile error
}
Consider returning a proxy object when you only want to permit const access, something like this (edited to fix the massive hole in the original code pointed out by #alagner!):
#include <iostream>
#include <vector>
template <class T> class proxy_vector
{
public:
proxy_vector (const std::vector<T *> &v) : m_v (v) { }
size_t size () { return m_v.size (); }
const T * const &operator[] (size_t i) const { return m_v [i]; }
// ... more functions as needed
private:
const std::vector <T *> &m_v;
};
class example
{
public:
example() : m_pv (bytePtrs_)
{
bytePtrs_.push_back(new char);
*bytePtrs_[0] = '$';
}
const proxy_vector <char> &getPtrs() { return m_pv; }
private:
std::vector<char*> bytePtrs_;
proxy_vector <char> m_pv;
};
int main()
{
example e;
auto &bytePtrs = e.getPtrs ();
// *bytePtrs [0] = 'x'; // uncomment to show that this code now actually works as intended!
std::cout << bytePtrs[0] << "\n";
}
A decent compiler should optimise most, if not all, of this away. Add access methods to proxy vector as needed, I doubt you will need many.
Demo (seems to work fine in C++11).
What #alagner suggests should also work and might be simpler. I haven't thought that through.
As the OP has pointed out in one of the comments, this is the API the code needs to comply to:
https://github.com/Xilinx/Vitis-AI/blob/master/src/Vitis-AI-Runtime/VART/vart/runner/include/vart/runner.hpp#L157
So by design it returns by copy, which is unavoidable really, thus what really can be done is this:
#include <vector>
#include <iostream>
class example {
public:
example() {
bytePtrs_.push_back(new char);
*bytePtrs_[0] = '$';
}
// Returning by value
// so shallow copy of objects is expected
// i.e. the pointers are copied
std::vector<const char*> getPtrs() {
return std::vector<const char*>(bytePtrs_.begin(), bytePtrs_.end());
}
private:
std::vector<char*> bytePtrs_;
};
int main() {
example e;
std::vector<const char*> bytePtrs = e.getPtrs();
std::cout << bytePtrs[0] << std::endl;
}
This is one of the very few cases where reinterpret_cast<> could be allowed into the code I think: since the std::vector<char *> and const std::vector<const char*>& are assumed to be compatible in memory anyways, you might cast. Thus, getPtrs() could actually return reinterpret_cast<const std::vector<const char*>&>(bytePtrs_);. To be clear: this is an optimization that relies on concrete ABI details (ItaniumABI et. al.), not generic standard C++, but I'm not yet aware of any architecture where it wouldn't work.
In c++20 and later, you might consider checking std::ranges::view.
There must be a trivial answer to this...
I have a std::set or a std::map or some object type which has a natural ordering - say std::less.
I need to change my set or map to contain shared_ptr instead of copies of T.
So I want something like:
using my_set std::set<std::shared_ptr<T>, std::less<*T>>;
But I'm drawing a blank as to how to specify "use the less adaptor on ____ adaptor of T so that it's on dereferenced members, not on shared_ptrs!"
Is there a std::less<std::dereference<std::shared_ptr<T>>> equivalent?
There is currently no functor in the C++ standard library to achieve what you want. You can either write a custom comparator, or if you need this functionality often, come up with an indirect/dereference function object.
Related and potentially helpful threads; the first one offers a generic solution for many operators (even if it requires a bit of code):
Why do several of the standard operators not have standard functors?
Functor that calls a function after dereferencing?
Less-than function dereferencing pointers
While the standard library may not already provide what you need, I think it's pretty trivial to write your own std::dereference_less:
#include <memory>
#include <set>
namespace std
{
template<typename T>
struct dereference_less
{
constexpr bool operator ()(const T& _lhs, const T& _rhs) const
{
return *_lhs < *_rhs;
}
};
}
int main()
{
using key_type = std::shared_ptr<int>;
std::set<key_type, std::dereference_less<key_type>> mySet;
}
Demo (refactored a bit to have a template type alias like in your question)
Since you are already changing your internal interface to something that requires dereferencing you could also just write a wrapper class and provide a bool operator< () as follows:
#include <memory> // shared_ptr
#include <set> // set
#include <iostream> // cout
using namespace std;
template<typename T>
class wrapper
{
public:
shared_ptr<T> sp;
bool operator< (const wrapper<T>& rhs) const
{
return *( sp.get() ) < *( rhs.sp.get() ) ;
}
wrapper(){}
wrapper(shared_ptr<T> sp):sp(sp){}
};
int main()
{
shared_ptr<int> sp1 (new int);
*sp1 = 1;
shared_ptr<int> sp2 (new int);
*sp2 = 2;
set<wrapper<int>> S;
S.insert(wrapper<int>(sp2));
S.insert(wrapper<int>(sp1));
for (auto& j : S)
cout << *(j.sp) << endl;
return 0;
}
I've been trying to streamline some of my code, condensing and making calls easier where I can. One of the things I've been trying to do is fuse two common overloads I have all over the place into one. They are as follows:
void MyClass::addSomething(Something & a)
{
vectorOfSomething.push_back(&a)
}
void MyClass::addSomething(std::vector<Something*> a)
{
for (unsigned int i = 0; i < a.size(); i++)
vectorOfSomething.push_back(a[i]);
}
The class Something is abstract. vectorOfSomething is a vector of pointers to Somethings.
Essentially, instead of having to do this:
std::Vector mySomethings = {&something1, &something2};
addSomething(mySomethings);
I want to do this:
addSomething({something1, something2});
So it is more similar to the first overload (no need for the user to create a vector of pointers first). Looking around the two ways I saw were either through: std::initializer_list or variadic templates, both of which I am not afraid to admit is completely foreign to me.
I've given it a shot with initializer lists but have run into a ton of errors trying various things. I've managed to get the function to actually accept the list, but I can't quite figure out how to get it to populate the vector correctly. The main issue seems to be that the init list has values that are 'const' within.
If anyone has any idea on how to make this work I would be grateful!
Something like this :
#include <iostream>
#include <initializer_list>
#include <vector>
#include <list>
struct MyClass {
template <typename It >
void Add( It b, It e ) {
data_.insert( end(data_), b, e );
}
void Add( std::initializer_list<int> const & elems ) {
Add( begin(elems), end(elems) );
}
template <typename T>
void Add( T const & cont ) {
Add( begin(cont), end(cont) );
}
std::vector<int> data_;
friend std::ostream & operator<<( std::ostream & os, MyClass const & mc ) {
for( auto & e : mc.data_ )
os << e << " ";
return os;
}
};
int main() {
MyClass foo;
foo.Add( { 1, 3 });
std::vector<int> v { 1,2};
foo.Add( v );
std::list<int> l { 4,5};
foo.Add( l );
std::cout << foo;
}
A compiler cannot infer a template argument to initializer_list, the specialization has to be explicit.
I need to implement an std::map with <std::string, fn_ptr> pairs. The function pointers are pointers to methods of the same class that owns the map. The idea is to have direct access to the methods instead of implementing a switch or an equivalent.
( I am using std::string as keys for the map )
I'm quite new to C++, so could anyone post some pseudo-code or link that talks about implementing a map with function pointers? ( pointers to methods owned by the same class that owns the map )
If you think there's a better approach to my problem, suggestions are also welcome.
This is about the simplest I can come up with. Note no error checking, and the map could probably usefully be made static.
#include <map>
#include <iostream>
#include <string>
using namespace std;
struct A {
typedef int (A::*MFP)(int);
std::map <string, MFP> fmap;
int f( int x ) { return x + 1; }
int g( int x ) { return x + 2; }
A() {
fmap.insert( std::make_pair( "f", &A::f ));
fmap.insert( std::make_pair( "g", &A::g ));
}
int Call( const string & s, int x ) {
MFP fp = fmap[s];
return (this->*fp)(x);
}
};
int main() {
A a;
cout << a.Call( "f", 0 ) << endl;
cout << a.Call( "g", 0 ) << endl;
}
A template implementation could look like:
class Factory {
public:
enum which {
foo, bar, baz
};
template<which w>
A* newA(...);
...
};
template<Factory::which w>
A* Factory::newA(...) {
/* default implementation */
throw invalid_argument();
}
template<>
A* Factory::newA<Factory::foo>(...) {
/* specialization for a 'foo' style A */
...
}
....
This requires that the value used to determine which newA is called be known at compile time. You could potentially use a const char * as the template parameter, but it's not guaranteed to work on all compilers.
Yet another option is to create helper factories, one for each factory creation method, and store those in the map. This isn't a huge advantage over storing method pointers, but does let you define a default creation method and simplifies fetching things from the map (there's no need to check that the key exists, because you'll get a default factory). On the downside, an entry for each unknown key would be added to the map.
Also, if you use an enum rather than a string for the key type, you shouldn't need to worry about checking whether a key exists in the map. While it's possible for someone to pass an invalid enum key to newA, they'd have to explicitly cast the argument, which means they're not going to do it by accident. I'm having a hard time imagining a case where someone would purposefully cause a crash in newA; the potential scenarios involve security, but an application programmer could crash the app without using your class.
Since C++14, we can use a generic lambda to get rid easily of pointers to member methods.
It follows a minimal, working example of a forward function made up with a generic lambda function:
#include<utility>
#include<map>
#include<string>
#include<iostream>
struct SomeClass { };
struct SomeOtherClass { };
struct Test {
void test(SomeClass) { std::cout << "SomeClass" << std::endl; }
void test(SomeOtherClass) { std::cout << "SomeOtherClass" << std::endl; }
};
int main() {
Test test;
auto l = [&test](auto c){ test.test(c); };
std::map<std::string, decltype(l)> m;
m.emplace("foo", l);
m.emplace("bar", l);
m.at("foo")(SomeClass{});
m.at("bar")(SomeOtherClass{});
}
Another option is to use delegates as oppose to function pointers. This delegate implementation is pretty fast, supports polymorphisms, and plays well with stl containers.
You could have something like:
class MyClass {
public:
// defines
typedef fastdelegate::FastDelegate2<int, int, int> MyDelegate;
typedef std::map<std::string, MyDelegate> MyMap;
// populate your map of delegates
MyClass() {
_myMap["plus"] = fastdelegate::MakeDelegate(this, &Plus);
_myMap["minus"] = fastdelegate::MakeDelegate(this, &Minus);
}
bool Do(const std::string& operation, int a, int b, int& res){
MyMap::const_iterator it = _myMap.find(operation);
if (it != _myMap.end()){
res = it.second(a,b);
return true;
}
return false;
}
private:
int Plus (int a, int b) { return a+b; }
int Minus(int a, int b) { return a-b; }
MyMap _myMap;
};