One can use the STL binary search algorithms (binary_search, upper_bound, lower_bound) to search a vector of Base pointers for a derived object, as shown below. Since Base is abstract (protected constructor), one has to instantiate a Derived object for the search functions, which is slightly ugly.
I want to search the vector for the first Derived above a given time. Can I do this without arbitrarily picking and instantiating one of my many inherited classes?
#include <algorithm>
#include <vector>
#include <stdio.h>
using namespace std;
class Base {
protected:
Base(double t, int d) : data(d), time(t) {}
public:
double time;
int data;
virtual void print() {
printf("Base: data = %d, time = %.1f\n",data,time);
}
};
class Derived : public Base {
public:
Derived(double t, int d) : Base(t,d) {}
virtual void print() {
printf("Derived: data=%d, time=%.1f\n",data,time);
}
};
struct BaseTimeComp {
bool operator()(Base* a, Base* b) { return a->time < b->time; }
};
int main()
{
vector<Base*> v;
for(int i=0; i<5; i++) { v.push_back(new Derived(i+0.4,i)); }
Base* pLow = *(lower_bound(v.begin(),v.end(),
new Derived(3.5,0), //NOT "new Base(3.5,0)"
BaseTimeComp()));
printf("lower bound for time=3.5:\n");
pLow->print();
}
The program prints:
lower bound for time=3.5:
Derived: data=4, time=4.4
The target of the comparison doesn't have to be the same type as the contents of the container, it just has to be something you can compare to the container:
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main()
{
vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
int i = *(lower_bound(v.begin(), v.end(), 1.5)); // <<< NOTE: floating point "value"
cout << i << endl;
}
Your assumption that you have to make some kind of Base is wrong. You can define a BaseKey which is suitable for your comparisons as long as your explicit (or implied) comparison operator knows what to do.
The comment below is also wrong, as this more complex example demonstrates:
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
struct A {
int x;
A(int _x) :x(_x) { }
bool operator < (double d) { return x < d; }
};
int main()
{
vector<A> v;
v.push_back(A(1));
v.push_back(A(2));
v.push_back(A(3));
int i = (lower_bound(v.begin(), v.end(), 1.5))->x;
cout << i << endl;
}
You can also use a comparision type explicitly (which helps with order of operations problems such as you might find with upper_bound):
class CompareADouble {
public:
bool operator () (const double d, A& a) { return d < a.x; }
};
int main()
{
vector<A> v;
v.push_back(A(1));
v.push_back(A(2));
v.push_back(A(3));
int i = (upper_bound(v.begin(), v.end(), 1.5, CompareADouble()))->x;
cout << i << endl;
}
A binary_search example providing both comparisons with polymorphism:
class CompareADouble {
public:
bool operator () (const double d, A& a) { return d < a.x; }
bool operator () (A& a, const double d) { return a.x < d; }
};
...
bool exists = binary_search(v.begin(), v.end(), 1.5, CompareADouble());
cout << exists << endl; // false
exists = binary_search(v.begin(), v.end(), 1.0, CompareADouble());
cout << exists << endl; // true because 1.0 < 1 == false && 1 < 1.0 == false
You could pass a null pointer, and design your comparison function ignore it, and only test the other object for a specific attribute.
You could, in a way, by using a static method:
class Base {
...
public:
static Base *newSearchInstance(double t, int d) {return new Base(t,d);};
...
};
and in the call to LowerBound:
Base* pLow = *(lower_bound(v.begin(),v.end(),
Base::newSearchInstance(3.5,0), //<------
BaseTimeComp()));
This means you don't have to have knowledge of any of the derived classes, but getting an instance of Base kind of defeats the purpose of Base being abstract in the first place. You would just as well make the constructor public.
Related
I have 2 classes A and B. I create objects which are then put into a multimap. I want to print the all the keys with their corresponding values. However, my attempt to do this was not so successfull as I could create an iterator. I would like to ask how can I use the equal_range() method to accomplish this. Thanks in advance!
#include "pch.h"
#include <iostream>
#include <map>
using namespace std;
class A {
int key;
public:
A(int k) {
key = k;
}
A(A ob) {
key = ob.key;
}
int getKey() {
return key;
}
};
class B {
string value;
public:
B(string v) {
value = v;
}
};
multimap <A, B> mp;
int main() {
mp = {
make_pair(A(1),B("Crime and punishment")),
make_pair(A(1),B("The Idiot")),
make_pair(A(1),B("Brothers' Karamazov")),
make_pair(A(2),B("Andreshko")),
make_pair(A(2),B("The Gerak family")),
make_pair(A(3),B("The name of the rose")),
make_pair(A(3),B("Baudolino"))
};
for (auto ml = mp.begin(); ml != mp.end();ml++) {
multimap<pair<int, string>, pair<int, string>>::iterator it;
}
}
You already have your loop, but let's use C++11 ranged-loop instead.
You are just missing an accessor for the value, so let's assume that you have it (getValue) and just access the iterator:
for (const auto& pair : mp) {
std::cout << ml.first.getKey() << "\t" << ml.second.getValue() << std::endl;
}
Also change this:
A(A ob)
To
A(const A& ob)
This will give a real copy assignment. But the default copy constructor is also fine, so don't mention it at all, the default one is already good for you.
Some things you need:
Getter methods for class B.
A less than operator for your key class A.
A copy constructor for class A.
In the code below if remove code not needed (but would be nice to keep in live code) to show what is really used.
#include <iostream>
#include <map>
#include <string>
using namespace std;
class A {
int key;
public:
A(int k) : key(k){}
A(A const& ob) : key(ob.key) {}
A& operator=(A const& ob) = delete;
int getKey() const { return key; }
friend bool operator<(A const&left, A const&right) { return left.key < right.key; }
};
class B {
string value;
public:
B(string const& v) : value(v) {}
B(B const&) = default;
B& operator=(B const&) = delete;
string const& getValue() const { return value; }
};
multimap<A, B> mp;
int main() {
mp = {
make_pair(A(3), B("Baudolino")),
make_pair(A(1), B("Crime and punishment")),
make_pair(A(1), B("Brothers' Karamazov")),
make_pair(A(2), B("Andreshko")),
make_pair(A(1), B("The Idiot")),
make_pair(A(2), B("The Gerak family")),
make_pair(A(3), B("The name of the rose"))
};
for (auto const & item : mp) {
cout << "key:" << item.first.getKey() << " value:\"" << item.second.getValue() << "\"\n";
}
}
I want to compare two objects and get larger among them using templates. Passing the object as an argument isn't working as the code below. See the sample code given below. That's what I'm trying to do.
#include <iostream>
using namespace std;
template <class T>
class max
{
T a;
public:
max(T a)
{
this.a = a;
}
T Large(T n2)
{
return (a > n2.a) ? a : n2.a;
}
};
int main()
{
max <int> obj1(10);
max <int> obj2(20);
cout<<obj1.Large(obj2)<<" is larger"<<endl;
return 0;
}
I'm doing something like this but by comparing 2 objects.
// class templates
#include <iostream>
using namespace std;
template <class T>
class mypair {
T a, b;
public:
mypair (T first, T second)
{a=first; b=second;}
T getmax ();
};
template <class T>
T mypair<T>::getmax ()
{
T retval;
retval = a>b? a : b;
return retval;
}
int main () {
mypair <int> myobject (100, 75);
cout << myobject.getmax();
return 0;
}
This code seems to work fine, let me know if this helps
#include <iostream>
using namespace std;
template <class T>
class Maxi {
T a;
public:
Maxi(T val)
{
this->a = val;
}
T Large(maxi n2)
{
return (a > n2.a) ? a : n2.a;
}
};
int main() {
Maxi <int> obj_1(10);
Maxi <int> obj_2(20);
cout<<obj_1.Large(obj_2)<<" is larger"<<endl;
return 0;
}
There is already a max and min template function provided under algorithm.
Just call std::max(10, 20) to get the larger between the two.
You can even provide your own comparator for custom comparison.
Side note: It seems like by including iostream, you can use max and min without algorithm.
Problems I see:
Use of
using namespace std;
is probably going to mess things up for you since std::max gets pulled into the mix indirectly. It does for me with g++. Don't use it.
Syntax error in the following line:
this.a = a;
That needs to be
this->a = a;
Argument to Large needs to be of type max, not T.
For good measure, I would also make it a const member function.
T Large(max n2) const
{
return (a > n2.a) ? a : n2.a;
}
Use std::cout and std::endl since using namespace std; is problematic.
Here's an updated version of your code with the above fixes:
#include <iostream>
template <class T>
class max
{
private:
T a;
public:
max(T a)
{
this->a = a;
}
T Large(max n2) const
{
return (a > n2.a) ? a : n2.a;
}
};
int main()
{
max <int> obj1(10);
max <int> obj2(20);
std::cout << obj1.Large(obj2) << " is larger"<<std::endl;
return 0;
}
It works for me and produces the following output:
20 is larger
I think you're trying to do this:
template <typename T>
T max(const T &a, const T &b)
{ return (b < a) ? a : b; }
That's how you do that. Your weird mishmash of a class doesn't make any sense at all. And so if I got what you're trying to do wrong, please explain yourself better.
Templates don't have to be classes you know. You can have templated functions.
If you absolutely must use a class, do this then:
template <typename T>
class max
{
T operator ()(const T &a, const T &b) { return (b < a) ? a : b; }
};
int main()
{
max<int> foo;
cout << foo(10, 20) << " is larger\n"; // Don't use endl most of the time.
return 0;
}
Suppose you have two objects that aren't ints, what do you do? Well, you do this:
#include <iostream>
#include <algorithm>
struct A {
int v1;
int v2;
};
bool operator <(A &a, A &b)
{
return (a.v1 < b.v1) || ((a.v1 == b.v1) && (a.v2 < b.v2));
}
::std::ostream &operator <<(::std::ostream &os, const A &a)
{
os << "{" << a.v1 << ", " << a.v2 << "}";
}
int main()
{
A first{10, 20};
B second{20, 10};
::std::cout << ::std::max(first, second) << " is the larger.\n";
}
If you don't want to have to define operator <, then do this:
bool my_less_than(const A &a, const A &b)
{
return (a.v1 < b.v1) || ((a.v1 == b.v1) && (a.v2 < b.v2));
}
int main()
{
A first{10, 20};
B second{20, 10};
::std::cout << ::std::max(first, second, my_less_than) << " is the larger.\n";
}
I need to do some equality checks with different types on a class hierarchy. In pseudo code:
#include <string>
#include <memory>
#include <iostream>
using namespace std;
class ComplexType {};
class Property {};
class IntegerProperty : public Property {
public:
int inner;
};
class StringProperty : public Property {
public:
string inner;
};
class ComplexTypeProperty : public Property {
ComplexType inner;
};
int main() {
shared_ptr<Property> p1 = getSomewhere(); //this is in fact a pointer on IntegerProperty
shared_ptr<Property> p2 = getSomewhere(); // this is in fact a pointer on StringProperty
shared_ptr<Property> p3 = getSomewhere(); // this is in fact a pointer on CompleyTypeProperty
ComplexType c;
cout << ((*p1) == 2);
cout << ((*p2) == "foo");
cout << ((*p3) == c);
}
It it simple to provide a operator== for the derived classes, but I cannot cast before checking, because the type of p1 and p2 is not clear at compile time.
Another way I know is to write the operator== function in the Property base class and throw some exceptions if the type is wrong, but I want, that the Property class can be subclassed later without changing the code for Property and it will work, too.
Templating Property is also not (directly) possible, because e.g. in my code a vector<shared_ptr<Property>> has to exist.
Is there some (generic) way to implement main() to get the equality checks, so that later subclassing of Property without changing the class itself is possible?
Have found some way of solving this. I'm not quite happy with the code. So if anyone has a better solution, please provide it.
#include <string>
#include <memory>
#include <iostream>
using namespace std;
class ComplexType {
public:
bool operator==(const ComplexType& i) {
return true;
}
};
inline ostream& operator<<(ostream& os, const ComplexType& c) {
os << "ComplexType";
return os;
}
class Property {
public:
virtual ~Property() {}
};
template <class T>
class LayerProperty : public Property {
private:
T inner;
public:
LayerProperty(T t) : inner(t) {}
bool operator==(const T i) {
return inner == i;
}
};
int main() {
shared_ptr<Property> p1 = make_shared<LayerProperty<int>>(LayerProperty<int>(5));
shared_ptr<Property> p2 = make_shared<LayerProperty<string>>(LayerProperty<string>("foo"));
shared_ptr<Property> p3 = make_shared<LayerProperty<ComplexType>>(LayerProperty<ComplexType>(ComplexType()));
ComplexType c;
cout << ((*dynamic_pointer_cast<LayerProperty<decltype(2)>>(p1)) == 2) << "\n";
// special case std::string
auto a = "foo";
auto s = "";
if (typeid(a) == typeid(s)) {
cout << ((*dynamic_pointer_cast<LayerProperty<decltype(string(a))>>(p2)) == a) << "\n";
}
cout << ((*dynamic_pointer_cast<LayerProperty<decltype(c)>>(p3)) == c) << "\n";
return 0;
}
I'm trying to design a piece of code that entails the use of an algorithm. The algorithm should be easily replaceable by someone else in the future. So in my LargeClass there has to be a way to invoke a specific algorithm.
I provided some example code below. My idea was to make an interface class IAlgorithm so that you have to provide an implementation yourself. I thought you could initialize it to which ever derived class you wanted in the constructor of the LargeClass. However the below code doesn't compile in VS2015 because IAlgorithm: cannot instantiate abstract class
My question: How should I design this in order to get the result I want?
Thanks in advance!
Algorithm.h
class IAlgorithm
{
protected:
virtual int Algorithm(int, int) = 0;
};
class algo1 : public IAlgorithm
{
public:
virtual int Algorithm(int, int);
};
class algo2 : public IAlgorithm
{
public:
virtual int Algorithm(int, int);
};
Algorithm.cpp
#include "Algorithm.h"
int algo1::Algorithm(const int a, const int b)
{
// Do something
}
int algo2::Algorithm(const int a, const int b)
{
// Do something
}
Source.cpp
#include "Algorithm.h"
class LargeClass
{
private:
IAlgorithm algo;
};
int main()
{
}
My first thoughts on this would be, why use such a primitive interface?
OK, we have a requirement that some process needs an algorithm sent into it. This algorithm must be polymorphic, it must take two ints and return an int.
All well and good. There is already a construct for this in the standard library. It's call a std::function. This is a wrapper around any function object with a compatible interface.
example:
#include <functional>
#include <iostream>
class LargeClass
{
public:
using algorithm_type = std::function<int(int,int)>;
LargeClass(algorithm_type algo)
: _algo(std::move(algo))
{}
int apply(int x, int y) {
return _algo(x,y);
}
private:
algorithm_type _algo;
};
int test(LargeClass&& lc) {
return lc.apply(5,5);
}
int divide(int x, int y) { return x / y; }
int main()
{
// use a lambda
std::cout << test(LargeClass{ [](auto x,auto y){ return x + y; } });
// use a function object
std::cout << test(LargeClass{ std::plus<>() } );
// use a free function
std::cout << test(LargeClass{ divide } );
// use a function object
struct foo_type {
int operator()(int x, int y) const {
return x * 2 + y;
}
} foo;
std::cout << test(LargeClass{ foo_type() } );
std::cout << test(LargeClass{ foo } );
}
I've got a class which acts as a combiner of a vector of pointers to an abstract base class. In the combined class there is a lot of repetition of the function that is used to combine the member functions together, e.g.
class Base {
public:
virtual double foo1(double x) = 0;
virtual double foo2(double x) = 0;
};
class Combined : public Base {
std::vector< std::shared_ptr<Base> > bases;
public:
double foo1(double x) {
double rv = 0.0;
for( auto& b : bases ) {
rv += b->foo1(x);
}
return rv;
}
double foo2(double x) {
double rv = 0.0;
for( auto& b : bases ) {
rv += b->foo2(x);
}
return rv;
}
};
It feels like I should be able to write one function to abstract that pattern away from having to repeat it for every method, so the Combined could be written in a way such as
class Combined : public Base {
std::vector< std::shared_ptr<Base> > bases;
public:
double foo1(double x) {
return combiner(foo1, x);
}
double foo2(double x) {
return combiner(foo2, x);
}
};
and there would be a combiner function along the lines of
double combiner(FuncName f, double x)
{
double rv = 0.0;
for( auto& b : bases ) {
rv += b->f(x);
}
return rv;
}
To reduce the quantity of boilerplate
Any help would be greatly appreciated.
It's called std::accumulate (found in <numeric>) and it can do exactly this.
#include <iostream>
#include <memory>
#include <algorithm>
using namespace std;
struct iFoo {virtual double foo() const=0;};
struct A : public iFoo {virtual double foo() const{return 10;}};
struct B : public iFoo {virtual double foo() const{return 20;}};
std::vector<std::unique_ptr<iFoo>> foos;//pretend its a member variable i'm lazy
//pretend its a member function (again, lazy)
template <typename T,typename K>
T xform_accumulate(T init,K xformer)
{
return std::accumulate(foos.cbegin(),foos.cend(),init,[xformer](T a,const std::unique_ptr<iFoo>& b) {return a+xformer(b);});
}
int main()
{
foos.push_back(std::unique_ptr<iFoo>(new A()));
foos.push_back(std::unique_ptr<iFoo>(new B()));
double x = xform_accumulate( 0.0, [](const std::unique_ptr<iFoo>& x){return x->foo();});
cout << "Hello World" << x << endl;
return 0;
}