c++ sort class with class vector inside - c++

I have a class cl1:
class c1
{
long double * coords;
...
}
I also have a second class cl2:
class cl2
{
vector<cl1*> cl1_vec;
unsigned int d;
...
}
I would like to sort cl1_vec, from cl2, based on coords[d], using the sort function for vectors.
So i could have something like
sort(cl2_inst->cl1_vec.begin(),cl2_inst->cl1_vec.end(), ??? );
I tried approches like
sort the 'std::vector' containing classes
C++ std::sort with predicate function in Class
but i couldn't make my way to solving this.
Thanks for any help that comes this way.
The code i've tried:
class cl1 {
public:
long double* coords;
cl1(long double *, unsigned int);
cl1();
cl1(const cl1& orig);
virtual ~cl1();
};
class cl2 {
public:
unsigned int d;
vector<cl1*> cl1_vec;
//the srting functions
static bool compareMyDataPredicate(cl1* lhs, cl1* rhs)
{
return (lhs->coords[d] < rhs->coords[d]);
};
// declare the functor nested within MyData.
struct compareMyDataFunctor : public binary_function<my_point*, my_point*, bool>
{
bool operator()( cl1* lhs, cl1* rhs)
{
return (lhs->coords[d] < rhs->coords[d]);
}
};
...
...
}
then in main
std::sort(cl2_inst->cl1_vec.begin(),cl2_inst->cl1_vec.end(),cl2::compareMyDataPredicate() );

The error is because you are accessing a non-static member d from a static context of the comparator function. Use the second approach, in the following way:
Provide a constructor to that struct, which takes a parameter unsigned int and sets a member to that value.
Create an object of type compareMyDataFunctor, and pass in the value of d to the constructor.
Use this object for sorting (3rd argument to std::sort)

I am not sure about the problems, because you were not precise enough about what exactly "does not work" means in your case (does not compile, does compile but does not sort etc). In case it does not compile (most likely guess) you did not post the error messages, which also makes finding and explaining the problem very hard.
Here are some guesses based on the code you posted:
Both static function as well as the functor use the member d to decide which column to sort on. However d is an instance variable, so it is not available for anything which is static. Neither the functor nor the static member function would know which of the possible ds to use, as there is one d per instance.
The best way to do this without resorting to C++11 features (lamdas) is to provide a constructor to the functor which takes the d you are planning to use. Something like this:
struct compareMyDataFunctor : public binary_function<cl1*, cl1*, bool>
{
compareMyDataFunctor( unsigned int d ) : d( d ) {}
bool operator()( cl1* lhs, cl1* rhs)
{
return (lhs->coords[d] < rhs->coords[d]);
}
unsigned int d;
};
This should do the trick.
There are some more things wrong with the code you posted though:
Arrays should be indexed using type size_t not a unsigned int. Same goes for std::vectors
The types in the std::binary_function instantiation do not match the actual types in the method (may be a problem of reducing the code).
Do not use using namespace std (I assume you do from the declarations in your code).
Functors such as these should take parameters as const-reference, not by value.
That's all I can think of. Next time try to present short, self contained, complete examples, then people will not have to resort to guessing.

Related

C++ how to initialize/copy const array member from array parameter in constructor

The following class is meant to store a single bool and an array of 100 integers. I want a constructor that takes as parameters a single bool and a 100-element array (which are then copied into the object). The obvious way to write this is the following
class Info {
private:
const int contents[100];
const bool symmetric;
public:
Info (const int contents[100], bool symmetric) : contents(contents), symmetric(symmetric) {}
// ...
};
But unfortunately this does not compile, the contents argument in the member initialiser list (the third contentson that line) seems to be regarded as a pointer.
Can I get this to work or is this a C++ limitation?
I do not want to use std::array or std::vector for space and efficiency reasons. [edited] Mine is a C++ syntax question and not about whether std::array is efficient or not. The answer may be useful in related situations that do not allow the use of std::array. [end edited]
Initializing in the constructor body does not work, because contents is const.
I am using C++14 with clang (CLion in linux) and come from the Java world.
There is also another way other than std::array, but you should use templates and use variadic parameter feature.
Lets assume that the number of elements is amount then first declare your class like :
#include <utility>
template<size_t amount, typename = std::make_index_sequence<amount> >
class Info;
then define your class as the following:
template<size_t amount, size_t ... _Idx>
class Info<amount, std::integer_sequence<size_t, _Idx...> > {
private:
const int contents[amount];
const bool symmetric;
public:
Info (const int contents_[amount], bool symmetric_) : contents{contents_[_Idx]...}, symmetric(symmetric_) {}
};
now you use your class for any amount without any problem:
const int preinfo[3] = {1,2,3};
Info<3> minfo(preinfo, true);
This method will make it very fast but please note that nothing is free and using this code will make your code to produce a bigger binary after compilation!

Downcasting `vector<Parent>`

I have a problem with upcasting and downcasting in my program. I have a vector<Child> that is passed to a function that expects const vector<Parent>& pp. There are no problems up to here (EDIT: apparently there are! See the comments). But, now I want to pass pp to a function that expects const vector<Child>& cc, Which I cannot do.
How should I do this, while at the same time I do not give the functions the ability to modify the original classes? Could you list various ways of doing this, preferably with their pros and cons?
There is a thing called variation. It comes in a 3 flavors:
invariation - even though B extends A, T<B> not extends T<A>,
covariation - when B extends A, then T<B> extends T<A>,
contravariation - when B extends A, then T<A> extends T<B>.
When it comes to C++ templates you end up with invariation. Even though by name it looks the same: vector<Parent> and vector<Child> those are 2 different types.
If you look at what is generated by compiler both of them operate on types which could potentially have different sizes. Since C++ rely on knowledge on object size (e.g. when it calculates position of object in an array) type e.g. Child[] cannot be casted to Parent[] because position of some object might be miscalculated. For the same reasons templates act in an invariant way: compiler cannot guess when it would and when it wouldn't be safe to perform such casting.
So it is up to you fix that and you have some options here. One would be making function that take that parameter template as well:
template<T>
void performAction(vector<T> objects) {
// ...
}
Other would be replacing values with a (smart) pointers - they would handle polymorphism easily.
EDIT:
To specify what I meant in the last sentence: you could simply use vector< unique_ptr<Parent> > or vector< shared_ptr<Parent> > to store any instance of Parent (including Child), so you won't have to perform any casting of the container.
Even if Child is derived from Parent or the other way round, vector<Child> and vector<Parent> are unrelated, they are different types.
You can have a template function template func(vector vec) { //do something based on the type of object passed }. Vectors are containers for objects so for a function which is expecting a vector &pp, if we pass vector && cc will not work and the code won't even compile.
We can use a code similar to:
class A
{
int i;
};
class B : public A
{
int j;
int k;
};
template<class T> void f(vector<T> &p)
{
//can handle both types now
}
int main()
{
B b1;
A a1;
vector<A> vectorA;
vectorA.push_back(a1);
vector<B> vectorB;
vectorB.push_back(b1);
f<B>(vectorB);
f<A>(vectorA);
return 0;
}
You can't. It's impossible.
Definitely don't do this:
template<typename TBase, typename TChild>
const std::vector<TBase*>& downcast(const std::vector<TChild*>& children)
{
static_assert(std::derived_from<TChild, TBase>);
return *reinterpret_cast<const std::vector<TBase*>*>(&children);
}

variant variable interaction with a non-variant type

I'm trying to solve the following problem. I have a vector (it's a custom structure actually, but a vector is a good enough substitute for this issue) of pointers to a custom class A. Class A can actually store either a type_a pointer or a type_b pointer (these types are quite different and are not related to each other). Right now that's implemented by keeping both, setting them to NULL and then having a bunch of if/else statements later on to check which type it is and perform appropriate action.
class A {
public:
A() : p1(NULL), p2(NULL) {}
type_a * p1;
type_b * p2;
};
std::vector<A *> v;
...
if (v[0]->p1 != NULL) { /* do this */ }
else if (v[0]->p2 != NULL) { /* do that */ }
I plan to add more pointers to class A, and so the above is starting to become a hassle. The solution that I'm currently trying to make work is using boost::variant instead, to have:
class A {
public:
boost::variant<type_a*, type_b*> p;
};
The problem I have encountered though, is that one of my actions involves calling a function that would assign some values to a variable depending on what type of p I have. This is what it is now and the appropriate process_stuff function is called inside one of the above if/else statements:
class B { /*...*/ };
void process_stuff(type_a * p, B * b) {
b->m_var = p->fn1();
}
void process_stuff(type_b * p, B * b) {
b->m_var = p->fn2();
}
I can't get this to work with boost::static_visitor since (as far as I understand) I can't have a non-variant type as an argument in binary visitation, nor can I have a non-const operator() to make the second variable a member of the visitor class and modify that inside operator() with unary visitation. So I'm confused how to convert the above process_stuff function to play along with boost::variant.
Btw I'm not attached to boost::variant and would take other solutions.
You just need a stateful visitor. I'm typing this from a vague memory of exactly what visitors look like, but you should be able to fix any mistakes I make.
class process_stuff_visitor : public boost::static_visitor<void> {
B* m_b;
public:
process_stuff_visitor(B* b) : m_b(b) {}
void visit(type_a* a) const { m_b->m_var = a->fn1(); }
void visit(type_b* b) const { m_b->m_var = b->fn2(); }
};
// actual processing:
boost::apply_visitor(v[0], process_stuff_visitor(the_b));
Alternatively since you assign to the same member of B, you could just extract the value-generating part.
struct generate_stuff_visitor : public boost::static_visitor<TypeOfMVar> {
TypeOfMVar visit(type_a* a) const { return a->fn1(); }
TypeOfMVar visit(type_b* b) const { return b->fn2(); }
};
the_b->m_var = boost::apply_visitor(v[0], generate_stuff_visitor());
A very general object-oriented way of doing what you want to do (if I understand you correctly) is to create a virtual base class for types a and b (and any further types you want) which defines a pure virtual method. This method will return something different for each type (for example, type_b::method could return 'b', while type_a::method could return 'a'), so when you call the method on your unspecified type, you will be told what type it is.
From there, you can use the return value of the identifying method to be the subject of a switch statement, or some other conventional control structure to invoke the correct behavior.

C++: use own class in a multiset container

at first I'm new here and English isn't my native language so apologize for any grammatical failures but I find this community really nice so I will try to ask my question as precise as I can.
I want to add my own class object into a stl container multiset and want to sort it with my own overloaded less operator defined in my class. I really tried out several solutions but nothing really worked so I hope someone can give me some useful hints to solve it.
Here is my general idea of my class definition:
class object {
public:
int first;
string second;
object(int f, string s) {
first = f;
second = s;
}
bool operator<(const object &comp) {
return first < comp.first;
}
};
This was my first try and it didn't work so I also tried out to declare the overloaded operator as a friend method but it didn't work also.
Here is a short code extract from my main function:
includes ...
//code omitted
int main() {
multiset<object*> mmset;
mmset.insert(new object(10, "test"));
mmset.insert(new object(11, "test"));
return 0;
}
After a while I started to debugging my code and try to figure out where the problem is and I come across the following thing that have made me a bit suspicious.
code extract from the stl:
// TEMPLATE STRUCT less
template<class _Ty>
struct less : public binary_function<_Ty, _Ty, bool>
{ // functor for operator<
bool operator()(const _Ty& _Left, const _Ty& _Right) const
{ // apply operator< to operands
return (_Left < _Right);
}
};
I have set a breakpoint on this line and observed what the program is doing here and I don't know why, but it only compares the addresses from the two objects and return so always false. It never calls my overloaded less operator although the operator exists and the _Left and _Right variables contain the address to my object.
I would really appreciate it if someone could help me.
Best Greetings
Tom
You are not storing objects in your multiset. You are storing object*s. These are pointers to objects. This means the set will order the pointers that you're inserting into it.
It seems like you really just want a multiset<object>:
multiset<object> mmset;
mmset.emplace(10, "test");
mmset.emplace(11, "test");
Now it will use < to compare the objects themselves.
If you really want to store pointers, you'll need to provide a custom comparator to the multiset. In C++11, you can do this easily with a lambda:
auto f = [](int* a, int* b) { return *a < *b; };
std::multiset<int*, decltype(f)> mmset(f);
Pre-C++11, you can create a function object that implements operator() with the same body as this lambda function.
Thank you for your help. That's seems to be a good solution to solve this problem.
I have searched a bit deeper in the new C++11 standard and found out that there is another possible solution to solve this with a little bit simpler implementation but the same result :)
I will post it just as information for other seekers with the same problem.
You can pass any constructor a stl container a so-called comparison object which the container will use to arrange your content.
The only thing you have to do is to define the overloaded operator() in your class and "misuse" them as a comparison operator.
class object {
int first;
string second;
object() { };
object(int f, string s) {
first = f;
second = s;
}
bool operator()(const object *comp1, const object *comp2) const {
return comp1->first < comp2->first;
}
}
The other thing what you have additionally to do now is to pass the object as the second argument in your definition of the container:
multiset(object*, object) mmset;
You can also use an extra class for this purpose just for comparison because otherwise you need a default constructor to use this class in this way.

when is better to use c++ template?

right now i am learning C++, and now I know the basic concept of template,
which act just like a generic type,
and i found almost every c++ program used template,
So i really want to know when are we supposed to use template ?
Can someone conclude your experience for me about c++ template ?
When will you consider to use template ?
Supplement:
if we defined such function
template <class myType>
myType GetMax (myType a, myType b) {
return (a>b?a:b);
}
but we want to pass a object(self-defined class) for comparison, how can we implement ?
Supplement2:
in the answer below, someone have wrote this sample code
template <class myType>
const myType& GetMax (const myType& a, const myType& b) {
return (a<b?b:a);
}
template <class myType, class Compare>
const myType& GetMax (const myType& a, const myType& b, Compare compare) {
return (compare(a,b)?b:a);
}
is this correct ? can we just pass a function name as a parameter of class myType ?
G'day,
Simple answer is when you want the behaviour to remain the same independent of the type being used to instantiate the class.
So a stack of ints will behave in the same way as a stack of floats will behave as a stack of MyClass objects.
Inheritance and base classes are used when you want to allow specialisation of the behaviour.
So say you have a base class called Animal and it has a member function called makeSound(). You have no idea which sound every animal will make so you make the makeSound member function a virtual function. In fact, because there is no default sound for all animals you have no idea what to have as default behaviour so you would declare this member function as a pure virtual function.
This then tells anyone making an instance of a derived class, for example a Lion class, that they must provide an implementation the makeSound member function which will provide a roar in some way.
Edit: I forgot to add that this is one of the articles in Scott Meyers's excellent book "Effective C++" (sanitised Amazon link) which I highly recommend.
HTH
cheers,
Basically when you want to create a generic class that can handle the solution for multiple types of classes, without having to have a parent-class for all the classes you want to support.
You can just give the class along with which you want to work with (best example would be a container, which can store any type that you pass along with the creation)
//----- the container
template <class T>
class Stack
{
public:
T* stackPtr;
}
//----- example
void main()
{
typedef Stack<float> FloatStack;
typedef Stack<int> IntStack;
}
Now you can store floats and ints with the same class without having to write a specific class for each type.
Short answer: if there is no use for it: don't.
If it seems to solve a problem (code reuse on different types,...), first implement and debug without templates and then add template parameters.
Before STL/boost, they were nice to make containers.
In the example you provided, everything is OK as long as operator > is defined for the data type whose instances you're comparing.
For example, if you define the following class:
class fraction
{
private:
int _num, _den;
public:
fraction(int num, int den)
{
if (den >= 0)
{
_num = num;
_den = den;
}
else
{
_num = -num;
_den = -den;
}
}
fraction(const fraction &f)
{
_num = f._num;
_den = f._den;
}
bool operator > (const fraction &f) const
{
return (_num * f._den) > (f._num * _den);
}
bool operator == (const fraction &f) const
{
return (_num * f._den) == (f._num * _den);
}
};
Then you can use your template function with instances of this class.
int main(int argc, char* argv[])
{
fraction a(1,2); // 0.5
fraction b(3,4); // 0.75
assert(GetMax/*<fraction>*/(a,b) == a);
return 0;
}
Re: supplement. If you want to pass a comparison function, you could provide another overload:
template <class myType>
const myType& GetMax (const myType& a, const myType& b) {
return (a<b?b:a);
}
template <class myType, class Compare>
const myType& GetMax (const myType& a, const myType& b, Compare compare) {
return (compare(a,b)?b:a);
}
Samle usage: to compare C-style strings:
bool c_strings_less(const char* a, const char* b)
{
return std::strcmp(a, b) < 0; //is a less than b
}
const char* greater = GetMax("hello", "world", c_strings_less);
This is how the std::max algorithm works. (I also made a few modifications, e.g it is customary in C++ that predicates define "less-than" comparison.)
Or if you asked, how GetMax would work for arbitrary user-defined types, then those must overload operator> or your function would result in a compile error.
When you need to parameterize concept represented by a class.
For example, if you have a class that represent a way to manage a type of object
class MyThingManager
{
void add( MyThing& mything );
//...
};
...maybe you need later to use exactly the same behaviour in a new type but managing a different type. Then you have the choice to use copy/paste/replace --that would lead hell opening under your feet immediately-- or make your class have a type to manage as parametter :
template< class ThingType >
class ThingManager
{
void add( ThingType& thing );
//...
};
That way you don't duplicate code.
Another concern is when you want some function call to be compatible with any parameter that have the required semantic :
template< class MyType >
void addPi( MyType& value )
{
value += PI;
}
That way you (again) don't have to duplicate code for each types possible in parametters.
It's not called "generic programming" for nothing.
Those are simple cases, but more complex cases exists, when you want to do some meta-programming. If you want to go there, please read at least one book before writing hell code. I recommand "C++ Template Meta-Programming" for that and the excellent "Modern C++ Design" book for more advanced template usage like Policy pattern ans other well known.
Answering the second question(
but we want to pass a object(self-defined class) for comparison, how can we implement?)
If you want to use your own class in a template function using the
operator >.
Your class need only to define this operator or function.
The important part is that your class need to define the same
the operator or function the template uses.
/Tobias
if you dont know the type of your variable or you want to do same thing for many types of variables, you can use template...
if you want to add 2 int, you want to get an int for return
if you want to add 2 double, you want to get an double for return
so you use template for this..
Template provide the way to parametrize on KNOWN AT COMPILE TIME quantities. Note that it can be a type (std::vector will contain only integers) but they can also be values:
template <int N, typename T > class MyType
is templatized both on an integer and a type, and MyType<2, int> will be a different type from MyType<3, int>.
Furthermore, templates allow for Template Metaprogramming: that is the compiler executes a program at compile time. There is a fascinating example by Erwin Unruh for computing primes at compile time.
Look at http://ubiety.uwaterloo.ca/~tveldhui/papers/priority.html for a small bit of history.
It's important to note that it's perfectly alright to not write your own templates. If you're not sure why you might need them, then you probably don't need them. Templates are a very powerful tool, but they are not always the best solution.
On any common development platform, the standard library provides a high-quality implementation of many of the old-school, traditional uses of templates. Using the standard library classes and functions doesn't require writing new templates. For instance, it provides std::max(), which is the same as your example.