This is in relation to an earlier question I had. I haven't managed to solve the problem there but for now I'm just trying to get better acquainted with the code to figure out how to deal with that problem.
Towards that goal, I've got around to trying out the suggestions given in that question and I'm a little stumped as to why the following isn't working.
in the header I have
class A {
public:
typedef std::multimap<int, double> intdoublemap_t;
const intdoublemap_t& getMap() const;
void setkey(int k);
void setvalue(double v);
void insertIntoMap();
intdoublemap_t mMapA;
private:
int key;
double value;
};
class B {
public:
typedef std::multimap<int, double> intdoublemap_t;
void mapValues(const A& a);
private:
intdoublemap_t mMapB;
};
in the implementation I have
const A::intdoublemap_t& A::getMap() const { return mMapA; }
void A::setkey(int k) { key = k; }
void A::setvalue(double v) { value = v; }
void A::insertIntoMap(){mMapA.insert(std::make_pair(key, value));}
void B::mapValues(const A & a){ const A::intdoublemap_t& mref = a.getMap();
mMapB = mref; }
and in main()
A a;
a.setkey(10);
a.setvalue(1232.2);
a.insertIntoMap();
B b;
b.mapValues(a);
The code compiles fine and everything to do with a works as expected but the map is not passing to b at all. It stays empty
Can anyone tell me why?
edit: I took another look at this and saw how to do it. I knew it was something stupidly basic. I just had to set mref in the function to a map in B and then could call a function to work on that map within B.
As #FrancoisAndrieux notes, your getMap() only sets a reference local to the function - not the class' intdoublemap_t mref. If you want the latter to be a reference to a map elsewhere, you have three options:
Make it intdoublemap_t& mref, initialize it on construction of the B instance.
Make it std::reference_wrapper<intdoublemap_t> mref, set it whenever you want (e.g. in mapValues().
Make it intdoublemap_t* (or std::shared_ptr<intdoublemap_t> in both A and B), set it whenever you like.
Note: As #FrancoisAndrieux says in a comment, with the second and third option (and without std::shared_ptr) you will have to be careful not to allow the reference to be used after the original object's lifetime has expired.
Having said all the above - I must also say that your design seems rather off to me. You should really not be doing any of these things and I'm 99% sure you're approaching your task the wrong way.
Related
I am currently taking a coding class at university and they have VERY specific requirements for the homework assignments.
For this week we have a class called Npt that represents a Nobel Prize winner. This class contains, amongst other things, the Name, the year of the prize and the field of the winner.
Now we should make another class, Nobelpreise, that contains a container for instances of said Nobel prize winner class. We are supposed to sort the elements of that container by the year of the Nobel Prize.
I wasn't able to use the std::sort function with a custom comparator correctly. This is what my code roughly looks like:
class Nobelpreise
{
private:
int numb;
vector<Npt> xx;
public:
Nobelpreise(){numb=0;}
void add(Npt &n1){xx.push_back(n1);numb++;return;}
Npt get_nobel(int i) {return xx[i];}
vector<Npt> get_xx() {return xx;}
int get_numb(){return numb;}
~Nobelpreise(){}
bool mycomp(Npt N1, Npt N2) {return (N1.get_jverl()<N2.get_jverl());}
};
The method get_jverl() comes from the Npt class and just returns the year.
Now the sort function always gives back an error saying that:
sort(Npl.get_xx().begin(), Npl.get_xx().end(), Npl.mycomp)
requires two arguments. Shouldn’t they be provided by the sort function?
I have also tried to overload the < operator which does not seem to work either.
edit1: added end() and removed the () from Npl.mycomp
edit2: we are required to make the comparator function a member of the class
Make your method mycomp static, and write a method which does the sort job.
class Nobelpreise
{
private:
int numb;
vector<Npt> xx;
public:
Nobelpreise(){numb=0;}
~Nobelpreise(){}
vector<Npt>& get_xx() {return xx;}
static bool mycomp( const Npt &N1, const Npt &N2 ) { return N1.get_jverl() < N2.get_jverl(); }
//^^^^^^
void Sort() { std::sort( xx.begin(), xx.end(), &mycomp ); }
};
The method Npt::get_jverl has to be const
returntype get_jverl() const { return ...; }
If you do the sorting outside your class note that you have to return a reference to your vector in your method: vector<Npt>& get_xx() {return xx;}
sort(Npl.get_xx().begin(), Npl.get_xx().end(), &Nobelpreise::mycomp)
Firstly, we'll fix the error that you're fetching two instances of the list:
sort(Npl.get_xx().begin(), Npl.get_xx().end, Npl.mycomp());
Replace with
auto v = Npl.get_xx();
std::sort(v.begin(), v.end(), Npl.mycomp());
I've added () to v.end, too, as we want to call it. However, we don't mean to call Npl::mycomp() here - std::sort wants to receive a function, not the return value:
auto v = Npl.get_xx();
std::sort(v.begin(), v.end(), Npl::mycomp);
This still won't work, as Npl::mycomp is an instance method, and std::sort won't call it with an object pointer for this. As it's implementation doesn't use this, it can be made a static method. Better still, it doesn't use any of the private members, so can be made a free function, outside of any class:
// I've renamed this to say what it does
bool year_precedes(const Npt& a, const Npt& b) {
return a.get_jverl() < b.get_jverl();
}
class Nobelpreise; // make the full declaration available
// for the following to compile
// I've made this a nonmember, too, as it only uses public methods
vector<Npt> sorted_prizes(const Nobelpreise& p)
{
auto v = p.get_xx();
std::sort(v.begin(), v.end(), year_precedes);
return v;
}
That should be enough to help you on your way.
You didn't say which version of C++, but assuming C++11 here's a more modern approach (compared to the two answers that are already here). Your requirements don't mention needing the comparator for anything else, so rather than write a comparator, you can do this:
std::sort(Npl.get_xx().begin(), Npl.get_xx().end(), [](const Npt& lhs, const Npt& rhs) {
return lhs.get_jverl() < rhs.get_jverl()
});
You could put this code in the Sort method of the Nobelpreise class as Rabbid suggests.
Compared to the other approaches here, I'd argue it makes the code more readable as you can see inline what is being compared, instead of having to jump to a new function just to read one more line of code (assuming of course that function is not being used anywhere else). It also makes the code faster because you are passing a lambda rather than a function pointer, but you shouldn't necessarily worry about that at this stage.
Disclaimer
I don't actually propose to apply this design anywhere, but I've been curious nonetheless how one would implement this in C++, in particular given C++'s lack of reflection. (I'm simultaneously learning and experimenting with C++11 features, so please do use C++11 features where helpful.)
The Effect
What I want to achieve is almost purely cosmetic.
I'd like a class that binds itself to an arbitrary number of, say, vectors, using referenced members (which, as I understand, must be initialized during construction), but provides "aliases" for accessing these vectors as members.
To give a minimal example, I want this to work—
std::vector<int> one;
std::vector<int> two;
std::vector<int> three;
Foo foo(std::make_pair('B', one),
std::make_pair('D', two),
std::make_pair('F', three));
foo.DoSomething();
where
class Foo
{
public:
// I'm using variadic templates here for sake of learning,
// but initializer lists would work just as well.
template <typename ...Tail>
Foo(std::pair<char, std::vector<int>&> head, Tail&&... tail) // : ???
{
// ???
}
virtual void DoSomething()
{
D.push_back(42);
std::cout << D[0] << std::endl;
}
private:
std::vector<int> A&, B&, C&, D&, E&, F&, G&; // and so on...
}
and also so that
std::cout << one[0] << std::endl; // outputs 42 from outside the class...
But you refuse to answer unless you know why...
Why would anyone want to do this? Well, I don't really want to do it, but the application I had in mind was something like this. Suppose I'm building some kind of a data analysis tool, and I have clients or operations people who know basic logic and C++ syntax, but don't understand OOP or anything beyond CS 101. Things would go a lot smoother if they could write their own DoSomething()s on the fly, rather than communicate every need to developers. However, it's not realistic to get them to set up UNIX accounts, teach them how to compile, and so on. So suppose instead I'd like to build an intranet web interface that lets them write the body of DoSomething() and configure what datasets they'd like to "alias" by an uppercase char, and upon submission, generates C++ for a child class of Foo that overrides DoSomething(), then builds, runs, and returns the output. (Suspiciously specific for a "hypothetical," eh? :-) Okay, something like this situation does exist in my world—however it only inspired this idea and a desire to explore it—I don't think it'd be worth actually implementing.) Obviously, this whole uppercase char ordeal isn't absolutely necessary, but it'd be a nice touch because datasets are already associated with standard letters, e.g. P for Price, Q for Quantity, etc.
The best I can do...
To be honest, I can't figure out how I'd make this work using references. I prefer using references if possible, for these reasons.
With pointers, I guess I'd do this—
class Foo
{
public:
template <typename ...Tail>
Foo(std::pair<char, std::vector<int>*> head, Tail&&... tail)
{
std::vector<int>[26] vectors = {A, B, C, D, E, F, G}; // and so on...
// I haven't learned how to use std::forward yet, but you get the picture...
// And dear lord, forgive me for what I'm about to do...
vectors[tail.first - 65] = tail.second;
}
virtual void DoSomething()
{
D->push_back(42);
std::cout << (*D)[0] << std::endl;
}
private:
std::vector<int> A*, B*, C*, D*, E*, F*, G*; // and so on...
}
But even that is not that elegant.
Is there a way to use references and achieve this?
Is there a way to make this more generic, e.g. use pseudo-reflection methods to avoid having to list all the uppercase letters again?
Any suggestions on alternative designs that would preserve the primary goal (the cosmetic aliasing I've described) in a more elegant or compact way?
You may use something like:
class Foo
{
public:
template <typename ...Ts>
Foo(Ts&&... ts) : m({std::forward<Ts>(ts)...}),
A(m.at('A')),
B(m.at('B'))
// and so on...
{
}
virtual void DoSomething()
{
A.push_back(42);
std::cout << A[0] << std::endl;
}
private:
std::map<char, std::vector<int>&> m;
std::vector<int> &A, &B; //, &C, &D, &E, &F, &G; // and so on...
};
but that requires that each vector is given, so
Foo(std::vector<int> (&v)[26]) : A(v[0]), B(v[1]) // and so on...
{
}
or
Foo(std::vector<int> &a, std::vector<int> &b /* And so on */) : A(a), B(b) // and so on...
{
}
seems more appropriate.
Live example.
And it seems even simpler if it is the class Foo which owns the vector, so you will just have
class Foo
{
public:
virtual ~Foo() {}
virtual void DoSomething() { /* Your code */ }
std::vector<int>& getA() { return A; }
private:
std::vector<int> A, B, C, D; // And so on
};
and provide getters to initialize internal vectors.
and then
std::vector<int>& one = foo.GetA(); // or foo.A if you let the members public.
Consider the following class member:
std::vector<sim_mob::Lane *> IncomingLanes_;
the above container shall store the pointer to some if my Lane objects. I don't want the subroutins using this variable as argument, to be able to modify Lane objects.
At the same time, I don't know where to put 'const' keyword that does not stop me from populating the container.
could you please help me with this?
thank you and regards
vahid
Edit:
Based on the answers i got so far(Many Thanks to them all) Suppose this sample:
#include <vector>
#include<iostream>
using namespace std;
class Lane
{
private:
int a;
public:
Lane(int h):a(h){}
void setA(int a_)
{
a=a_;
}
void printLane()
{
std::cout << a << std::endl;
}
};
class B
{
public:
vector< Lane const *> IncomingLanes;
void addLane(Lane *l)
{
IncomingLanes.push_back(l);
}
};
int main()
{
Lane l1(1);
Lane l2(2);
B b;
b.addLane(&l1);
b.addLane(&l2);
b.IncomingLanes.at(1)->printLane();
b.IncomingLanes.at(1)->setA(12);
return 1;
}
What I meant was:
b.IncomingLanes.at(1)->printLane()
should work on IncomingLanes with no problem AND
b.IncomingLanes.at(1)->setA(12)
should not be allowed.(In th above example none of the two mentioned methods work!)
Beside solving the problem, I am loking for good programming practice also. So if you think there is a solution to the above problem but in a bad way, plase let us all know.
Thaks agian
A detour first: Use a smart pointer such shared_ptr and not raw pointers within your container. This would make your life a lot easy down the line.
Typically, what you are looking for is called design-const i.e. functions which do not modify their arguments. This, you achieve, by passing arguments via const-reference. Also, if it is a member function make the function const (i.e. this becomes const within the scope of this function and thus you cannot use this to write to the members).
Without knowing more about your class it would be difficult to advise you to use a container of const-references to lanes. That would make inserting lane objects difficult -- a one-time affair, possible only via initializer lists in the ctor(s).
A few must reads:
The whole of FAQ 18
Sutter on const-correctness
Edit: code sample:
#include <vector>
#include <iostream>
//using namespace std; I'd rather type the 5 characters
// This is almost redundant under the current circumstance
#include <vector>
#include <iostream>
#include <memory>
//using namespace std; I'd rather type the 5 characters
// This is almost redundant under the current circumstance
class Lane
{
private:
int a;
public:
Lane(int h):a(h){}
void setA(int a_) // do you need this?
{
a=a_;
}
void printLane() const // design-const
{
std::cout << a << std::endl;
}
};
class B
{
// be consistent with namespace qualification
std::vector< Lane const * > IncomingLanes; // don't expose impl. details
public:
void addLane(Lane const& l) // who's responsible for freeing `l'?
{
IncomingLanes.push_back(&l); // would change
}
void printLane(size_t index) const
{
#ifdef _DEBUG
IncomingLanes.at( index )->printLane();
#else
IncomingLanes[ index ]->printLane();
#endif
}
};
int main()
{
Lane l1(1);
Lane l2(2);
B b;
b.addLane(l1);
b.addLane(l2);
//b.IncomingLanes.at(1)->printLane(); // this is bad
//b.IncomingLanes.at(1)->setA(12); // this is bad
b.printLane(1);
return 1;
}
Also, as Matthieu M. suggested:
shared ownership is more complicated because it becomes difficult to
tell who really owns the object and when it will be released (and
that's on top of the performance overhead). So unique_ptr should be
the default choice, and shared_ptr a last resort.
Note that unique_ptrs may require you to move them using std::move. I am updating the example to use pointer to const Lane (a simpler interface to get started with).
You can do it this way:
std::vector<const sim_mob::Lane *> IncomingLanes_;
Or this way:
std::vector<sim_mob::Lane const *> IncomingLanes_;
In C/C++, const typename * and typename const * are identical in meaning.
Updated to address updated question:
If really all you need to do is
b.IncomingLanes.at(1)->printLane()
then you just have to declare printLane like this:
void printLane() const // Tell compiler that printLane doesn't change this
{
std::cout << a << std::endl;
}
I suspect that you want the object to be able to modify the elements (i.e., you don't want the elements to truly be const). Instead, you want nonmember functions to only get read-only access to the std::vector (i.e., you want to prohibit changes from outside the object).
As such, I wouldn't put const anywhere on IncomingLanes_. Instead, I would expose IncomingLanes_ as a pair of std::vector<sim_mob::Lane *>::const_iterators (through methods called something like GetIncomingLanesBegin() and GetIncomingLanesEnd()).
you may declare it like:
std::vector<const sim_mob::Lane *> IncomingLanes_;
you will be able to add, or remove item from array, but you want be able to change item see bellow
IncomingLanes_.push_back(someLine); // Ok
IncomingLanes_[0] = someLine; //error
IncomingLanes_[0]->some_meber = someting; //error
IncomingLanes_.erase(IncomingLanes_.end()); //OK
IncomingLanes_[0]->nonConstMethod(); //error
If you don't want other routines to modify IncomingLanes, but you do want to be able to modify it yourself, just use const in the function declarations that you call.
Or if you don't have control over the functions, when they're external, don't give them access to IncomingLanes directly. Make IncomingLanes private and provide a const getter for it.
I don't think what you want is possible without making the pointers stored in the vector const as well.
const std::vector<sim_mob::Lane*> // means the vector is const, not the pointer within it
std::vector<const sim_mob::Lane*> // means no one can modify the data pointed at.
At best, the second version does what you want but you will have this construct throughout your code where ever you do want to modify the data:
const_cast<sim_mob::Lane*>(theVector[i])->non_const_method();
Have you considered a different class hierarchy where sim_mob::Lane's public interface is const and sim_mob::Really_Lane contains the non-const interfaces. Then users of the vector cannot be sure a "Lane" object is "real" without using dynamic_cast?
Before we get to const goodness, you should first use encapsulation.
Do not expose the vector to the external world, and it will become much easier.
A weak (*) encapsulation here is sufficient:
class B {
public:
std::vector<Lane> const& getIncomingLanes() const { return incomingLanes; }
void addLane(Lane l) { incomlingLanes.push_back(l); }
private:
std::vector<Lane> incomingLanes;
};
The above is simplissime, and yet achieves the goal:
clients of the class cannot modify the vector itself
clients of the class cannot modify the vector content (Lane instances)
and of course, the class can access the vector content fully and modify it at will.
Your new main routine becomes:
int main()
{
Lane l1(1);
Lane l2(2);
B b;
b.addLane(l1);
b.addLane(l2);
b.getIncomingLanes().at(1).printLane();
b.getIncomingLanes().at(1).setA(12); // expected-error\
// { passing ‘const Lane’ as ‘this’ argument of
// ‘void Lane::setA(int)’ discards qualifiers }
return 1;
}
(*) This is weak in the sense that even though the attribute itself is not exposed, because we give a reference to it to the external world in practice clients are not really shielded.
I am trying to get the hang of C++ pointers and objects, through a small project implementing a simple Vehicle Routing Problem. Even though my code is currently working, I can't shake the feeling that my approach is completely wrong. What bugs me, are snippets of code such as :
std::map<const Route*, double>::iterator it = quantities.begin();
if ((*(*(it->first)).getDestination()).getDemand() > (*(*(it->first)).getDeparture()).getSupply())
The pointer hell situation in the if condition is the result of the get methods returning pointers to already created objects. The methods being called are :
const Departure* Route::getDeparture() const {
return departure;
};
const Destination* Route::getDestination() const {
return destination;
};
and
int Destination::getDemand() const {
return demand;
};
int Departure::getSupply() const {
return supply;
};
Am I completely off track here, am i missing something or is this type of situtation something normal?
To increase readability you can change *s to ->:
if(it->first->getDestination()->getDemand() > it->first->getDeparture()->getSupply())
Also, if you aren't going to give up ownership of that object (and you aren't, in this case) it is better to return by const reference:
const Departure& Route::getDeparture() const {
return *departure;
};
and use ., not ->:
if(it->first->getDestination().getDemand() > it->first->getDeparture().getSupply())
instead of (*p).x write p->x.
Trying to learn something new every day I'd be interested if the following is good or bad design.
I'm implementing a class A that caches objects of itself in a static private member variable std::map<> cache. The user of A should only have access to pointers to elements in the map, because a full copy of A is expensive and not needed. A new A is only created if it is not yet available in the map, as construction of A needs some heavy lifting. Ok, here's some code:
class B;
class A {
public:
static A* get_instance(const B & b, int x) {
int hash = A::hash(b,x);
map<int, A>::iterator found = cache.find(hash);
if(found == cache.end())
found = cache.insert(make_pair(hash, A(b,x))).first;
return &(found->second);
}
static int hash(B & b, int x) {
// unique hash function for combination of b and x
}
// ...
private:
A(B & b, int x) : _b(b), _x(x) {
// do some heavy computation, store plenty of results
// in private members
}
static map<int, A> cache;
B _b;
int _x; // added, so A::hash() makes sense (instead of B::hash())
// ...
};
Is there anything that is wrong with the code above? Are there any pitfalls,
do I miss memory management problems or anything else?
Thank you for your feedback!
The implementation is intended to only allow you to create items via get_instance(). You should ideally make your copy-constructor and assignment operator private.
It would not be thread-safe. You can use the following instead:
const boost::once_flag BOOST_ONCE_INIT_CONST = BOOST_ONCE_INIT;
struct AControl
{
boost::once_flag onceFlag;
shared_ptr<A> aInst;
void create( const B&b, int x )
{
aInst.reset( new A(b, x) );
}
AControl() : onceFlag( BOOST_ONCE_INIT_CONST )
{
}
A& get( const B&b, int x )
{
boost::call_once( onceFlag, bind( &AOnceControl::create, this, b, x ) );
return *aInst;
}
};
Change the map to
map
Have a mutex and use it thus:
AControl * ctrl;
{
mutex::scoped_lock lock(mtx);
ctrl = &cache[hash];
}
return ctrl->get(b,x);
Ideally only get_instance() will be static in your class. Everything else is private implementation detail and goes into the compilation unit of your class, including AControl.
Note that you could do this a lot simpler by just locking through the entire process of looking up in the map and creating but then you are locking for longer whilst you do the long construction process. As it is this implements record-level locking once you have inserted the item. A later thread may find the item uninitialised but the boost::once logic will ensure it is created exactly once.
Any time you use globals (in this case the static map) you have to worry about concurrency issues if this is used across multiple threads. For example, if two threads were trying to get a particular instance at once, they could both create an object resulting in duplicates. Even worse, if they both tried to update the map at the same time it could get corrupted. You'd have to use mutexes to control access to the container.
If it's single-threaded only then there's no issue until someone decides it needs to be made multi-threaded in the future.
Also as a style note, while names starting with underscore+lower case letter are technically legal, avoid any symbols starting with underscores will avoid possibly accidentally breaking the rules and getting weird behavior.
I think these are 3 separate things that you mix together inside A:
the class A itself (what its intances are supposed to do).
poolling of instances for cache purposes
having such a static singlton pool for a certain type
I think they should be separate in the code, not all together inside A.
That means:
write your class A without any consideration of how it should be allocated.
write a generic module to perform pool cache of objects, along the lines of:
*
template< typename T > class PoolHashKey { ... };
template< typename T > class PoolCache
{
//data
private: std::map< .... > map_;
//methods
public: template< typename B > PoolKey< T > get_instance( B b );
public: void release_instance( PoolKey< T > );
// notice that these aren't static function members
};
create a singleton instance of PoolCache somewhere and use it:
*
PoolCache<A>& myAPool()
{
static PoolCache<A> s;
return s;
//you should use some safe singleton idiom.
}
int main()
{
B b;
PoolKey<A> const aKey( myAPool().get_instance( b );
A* const a( aKey.get() );
//...
myAPool().release_instance( aKey ); //not using it anymore
/*or else the destructor of PoolKey<A> should probably do some reference count and let the pool know this instace isn't needed anymore*/
}