passing object dependent comparator as template argument, - c++

I have a class which is similar to following. I am using pairing heap of boost library which needs comparator as template argument. My comparator should access the data and member of class A to make comparisions. Initially, I declared 'my_compare' as struct and overloaded the () operator. But the struct could not access data of class A unless the pointer('this') to class A was passed to it. But that would mean my_compare no longer remains a compile time constant, and it would produce error: 'this' cannot appear in constant expression.
As a second attempt I declared my_compare as a member function (so that it can access the members and data). I get following error now:
error: type/value mismatch at argument 1 in template parameter list for
‘template<class T> struct boost::heap::compare’
I suspect two possible explanations: 'my_compare' is not an (function)object and it is not a binary function as 'this' is implicitely passed. How can I solve this issue.
class A{
public:
//some data(properties)
struct c{
//some data
};
double method1(int variable);
double method2(const struct c&);
bool my_compare(struct c& c, struct c& d){
//accesses member methods and data
}
typedef boost::heap::pairing_heap<struct c, boost::heap::compare<my_compare> > myheap;
}

You need to store an A* inside c. Perhaps like this:
class A{
public:
//some data(properties)
struct c{
//some data
A* owner_A;
c(A* a) : owner_A(a) {}
};
double method1(int variable);
double method2(const struct c&);
static bool my_compare(struct c& c, struct c& d){
//accesses member methods and data
c->owner_A->method1(42);
d->owner_A->method2(d);
}
typedef boost::heap::pairing_heap<struct c, boost::heap::compare<my_compare> > myheap;
}

First things first: The my_compare function either has to be a free-standing function, or made static. There's really no way around it in your situation.
However, if you really need to access members in the A class, then you can make pointer in the c structure to an A instance:
struct c
{
A* a;
// Other members
};
Then when you create a c object you set the a pointer to this.

Than you should use a functor.
class A {
struct my_compare;
friend struct my_compare;
struct my_compare {
A &self;
A(A &self) : self(self) {}
bool operator()(struct c& c, struct c& d) {
// access member data and methods on self
}
};
}
Of course you have to tell it which A instance to use, so you'll have to construct it like my_compare(*this) when constructing the heap.
Note, that you have to make the inner class a friend, it is not automatic. You can either declare it, make it a friend and define it, or you can define it, make it a friend, but than you have to put the operator body outside of the class.

Related

How to deal with constructor when input-output type is different for templated class

I'm learning C++ for only a short period of time and the following problem gives me headache.
What I'm trying to do is basiclly to wrap an existing library without introducing too much overhead such that the wrapper library could run as fast as the existing one. Therefore, I tend to not modify anything in existing library. I'm doing this in order to make the interface(syntax) compatible with my old codes.
Say, the existing class is called BASE, which is also templated class.
There are a few ways to do the wrapping such as inheritance. I decided to go with the option of including BASE as a member of Wrapper class for better encapsulation.
template<class T>
class Wrapper{
public:
Wrapper() : base(){};
/*error line*/ Wrapper( const Wrapper<double>& a, const Wrapper<double>& b ) : base(a.base, b.base){};
// constuct Wrapper<complex<double>> vector from two Wrapper<double> vectors using constuctor from existing class BASE
// 'a', 'b' are real and imag part respectively.
private:
BASE<T> base;
};
The following line couldn't compile, error message is 'base is declared as private within the context'
/*error line*/ Wrapper( const Wrapper<double>& a, const Wrapper<double>& b ) : base(a.base, b.base){};
Experiments I have done so far:
<1>. change
private:
BASE<T> base;
to
public:
BASE<T> base;
the code complies and gives correct answer. But, as I stated above, I want data encapsulation, so this solution is a no go.
<2>. Although the error message suggests there is something to do with the access privilege, I think this is caused by different input-output type (inputs are two "double", output is type of "complex double"). The following dosomething() function works as long as the type of input and type of (*this) are consistent, no error regarding 'base is declared as private within the context'.
template<class T>
class Wrapper{
public:
Wrapper() : base(){};
/*error line*/ Wrapper( const Wrapper<double>& a, const Wrapper<double>& b ) : base(a.base, b.base){};
void dosomething(const Wrapper<T>& a)
{
(*this).base = a.base; // ok, compiles good
}
private:
BASE<T> base;
};
How to work around? Look forwarding to any useful comments.
You may make your class friend of the same class but with different parameter:
template<class T>
class Wrapper{
template <typename U> friend class Wrapper;
public:
Wrapper() : base(){}
Wrapper(const Wrapper<double>& a, const Wrapper<double>& b) : base(a.base, b.base){}
private:
BASE<T> base;
};

What's the closest thing in C++ to retroactively defining a superclass of a defined class?

Suppose I have the class
class A {
protected:
int x,y;
double z,w;
public:
void foo();
void bar();
void baz();
};
defined and used in my code and the code of others. Now, I want to write some library which could very well operate on A's, but it's actually more general, and would be able to operate on:
class B {
protected:
int y;
double z;
public:
void bar();
};
and I do want my library to be general, so I define a B class and that's what its APIs take.
I would like to be able to tell the compiler - not in the definition of A which I no longer control, but elsewhere, probably in the definition of B:
Look, please try to think of B as a superclass of A. Thus, in particular, lay it out in memory so that if I reinterpret an A* as a B*, my code expecting B*s would work. And please then actually accept A* as a B* (and A& as a B& etc.).
In C++ we can do this the other way, i.e. if B is the class we don't control we can perform a "subclass a known class" operation with class A : public B { ... }; and I know C++ doesn't have the opposite mechanism - "superclass a known class A by a new class B". My question is - what's the closest achievable approximation of this mechanism?
Notes:
This is all strictly compile-time, not run-time.
There can be no changes whatsoever to class A. I can only modify the definition of B and code that knows about both A and B. Other people will still use class A, and so will I if I want my code to interact with theirs.
This should preferably be "scalable" to multiple superclasses. So maybe I also have class C { protected: int x; double w; public: void baz(); } which should also behave like a superclass of A.
You can do the following:
class C
{
struct Interface
{
virtual void bar() = 0;
virtual ~Interface(){}
};
template <class T>
struct Interfacer : Interface
{
T t;
Interfacer(T t):t(t){}
void bar() { t.bar(); }
};
std::unique_ptr<Interface> interface;
public:
template <class T>
C(const T & t): interface(new Interfacer<T>(t)){}
void bar() { interface->bar(); }
};
The idea is to use type-erasure (that's the Interface and Interfacer<T> classes) under the covers to allow C to take anything that you can call bar on and then your library will take objects of type C.
I know C++ doesn't have the opposite mechanism - "superclass a known
class"
Oh yes it does:
template <class Superclass>
class Class : public Superclass
{
};
and off you go. All at compile time, needless to say.
If you have a class A that can't be changed and need to slot it into an inheritance structure, then use something on the lines of
template<class Superclass>
class Class : public A, public Superclass
{
};
Note that dynamic_cast will reach A* pointers given Superclass* pointers and vice-versa. Ditto Class* pointers. At this point, you're getting close to Composition, Traits, and Concepts.
Normal templates do this, and the compiler will inform you when you use them incorrectly.
instead of
void BConsumer1(std::vector<B*> bs)
{ std::for_each(bs.begin(), bs.end(), &B::bar); }
void BConsumer2(B& b)
{ b.bar(); }
class BSubclass : public B
{
double xplusz() const { return B::x + B::z; }
}
you write
template<typename Blike>
void BConsumer1(std::vector<Blike*> bs)
{ std::for_each(bs.begin(), bs.end(), &Blike::bar); }
template<typename Blike>
void BConsumer2(Blike& b)
{ b.bar(); }
template<typename Blike>
class BSubclass : public Blike
{
double xplusz() const { return Blike::x + Blike::z; }
}
And you use BConsumer1 & BConsumer2 like
std::vector<A*> as = /* some As */
BConsumer1(as); // deduces to BConsumer1<A>
A a;
BConsumer2(a); // deduces to BConsumer2<A>
std::vector<B*> bs = /* some Bs */
BConsumer1(bs); // deduces to BConsumer1<B>
// etc
And you would have BSubclass<A> and BSubclass<B>, as types that use the B interface to do something.
There is no way to change the behaviour of a class without changing the class. There is indeed no mechanism for adding a parent class after A has already been defined.
I can only modify the definition of B and code that knows about both A and B.
You cannot change A, but you can change the code that uses A. So you could, instead of using A, simply use another class that does inherit from B (let us call it D). I think this is the closest achievable of the desired mechanism.
D can re-use A as a sub-object (possibly as a base) if that is useful.
This should preferably be "scalable" to multiple superclasses.
D can inherit as many super-classes as you need it to.
A demo:
class D : A, public B, public C {
public:
D(const A&);
void foo(){A::foo();}
void bar(){A::bar();}
void baz(){A::baz();}
};
Now D behaves exactly as A would behave if only A had inherited B and C.
Inheriting A publicly would allow getting rid of all the delegation boilerplate:
class D : public A, public B, public C {
public:
D(const A&);
};
However, I think that could have potential to create confusion between code that uses A without knowledge of B and code that uses knows of B (and therefore uses D). The code that uses D can easily deal with A, but not the other way 'round.
Not inheriting A at all but using a member instead would allow you to not copy A to create D, but instead refer to an existing one:
class D : public B, public C {
A& a;
public:
D(const A&);
void foo(){a.foo();}
void bar(){a.bar();}
void baz(){a.baz();}
};
This obviously has potential to mistakes with object lifetimes. That could be solved with shared pointers:
class D : public B, public C {
std::shared_ptr<A> a;
public:
D(const std::shared_ptr<A>&);
void foo(){a->foo();}
void bar(){a->bar();}
void baz(){a->baz();}
};
However, this is presumably only an option if the other code that doesn't know about Bor D also uses shared pointers.
This seems more like static polymorphism rather dynamic. As #ZdeněkJelínek has already mentioned, you could you a template to ensure the proper interface is passed in, all during compile-time.
namespace details_ {
template<class T, class=void>
struct has_bar : std::false_type {};
template<class T>
struct has_bar<T, std::void_t<decltype(std::declval<T>().bar())>> : std::true_type {};
}
template<class T>
constexpr bool has_bar = details_::has_bar<T>::value;
template<class T>
std::enable_if_t<has_bar<T>> use_bar(T *t) { t->bar(); }
template<class T>
std::enable_if_t<!has_bar<T>> use_bar(T *) {
static_assert(false, "Cannot use bar if class does not have a bar member function");
}
This should do what you'd like (i.e. use bar for any class) without having to resort to a vtable lookup and without having the ability to modify classes. This level of indirection should be inlined out with proper optimization flags set. In other words you'll have the runtime efficiency of directly invoking bar.

Passing std::vector of derived type where a std::vector of base type is expected

I have a base class:
class Member
{
....
}
and a derived class, like this:
class Mine_sweeper : private Member
{
....
}
Then I have a container:
class Population
{
public:
std::vector<Member>& m_members;
Population(std::vector<Member>& members);
}
When I use Population's constructor with a vector of Members it compiles OK. But if I try to link Population's m_members with a vector of Mine_sweepers, complier throws an error.
std::vector<Member> members;
Population pop(members); // this compiles OK
std::vector<Mine_sweeper> sweepers;
Population pop(sweepers); // but here I get an error
main.cpp(23): error C2664: 'Population::Population(std::vector &)' : cannot convert parameter 1 from 'std::vector' to 'std::vector &'
Vector of Mine_sweepers is not a "kind of" vector of Members, even when Mine_sweeper is a "kind of" Member. You can not use vector<Derived> in place of vector<Base>.
Use vector<unique_ptr<Member>> instead of vector<Member> AND vector<Mine_sweeper>. This enables you to have heterogeneous Population of Members (i.e. Mine_sweepers and other Member sub-types, at the same time).
Alternatively, convert the Population class to a class template:
class Population<T>
{
public:
std::vector<T>& m_members;
Population(std::vector<T>& members);
}
This way, one Population instance may only contain one type of Members.
You can't. Not as is. This is because std::vector<B> is not derived from std::vector<A>, regardless of the fact that B is derived from A.
But wait ... let us simplify your problem with a minimal example:
struct A {};
struct B : A {};
void f(std::vector<A> const&) {}
int main()
{
std::vector<A> vecA;
std::vector<B> vecB;
f(vecA);
f(vecB); // error
}
Here, unlike in your sample code, B publicly inherits from A. You still can't give a std::vector<B> const& to a function expecting a std::vector<A> const& because there exists no implicit conversion from std::vector<B> to std::vector<A>.
In the following case, one can send a B const& where a A const& is expected because C++ provide an implicit conversion from reference to a derived type to a reference to a base type.
struct A {};
struct B : A {};
void f(A const&) {}
int main()
{
A alice;
B bob;
f(alice);
f(bob);
}
A solution is to provide an explicit conversion using the existing implicit conversion from B to A:
struct A {};
struct B : A {};
class Container
{
std::vector<A*> _items;
public:
template<class T>
Container(std::vector<T> v)
: _items(v.begin(), v.end())
{}
// other stuff, see rule of 5
};
int main()
{
std::vector<A*> vecA;
std::vector<B*> vecB;
Container contA(vecA);
Container contB(vecB);
}
Once you have a basic working conversion, you need to figure out how to handle memory ownership with std::unique_ptr, std::shared_ptr and std::weak_ptr.
The constructor for the Population class takes an argument to a vector holding an array of Member class. You're right that you can pass a derived class to something that takes the base class as argument, or upcast from derived to base, but what you're doing here is different. You're not sending a derived class to a function taking a base class argument, you're sending a different unrelated type altogether, you're sending an std::vector< typeA> to something that wants std::vector< typeB>.
When you create std::vector< int> at compile time it will create the vector class with all the specific details specific to how it for example iterates over the ints etc. This is an array or "ints". Would it make sense to pass it to a function that takes an array of doubles? Then the function is doing work on doubles, for example to move to the next double it might move forward 8 bytes instead of 4, it would be doing the wrong thing.
You would have to make two versions of the Population class manually or use templates to do it. Edit: See YSC's answer, he templates the constructor
Or, you probably want one vector/array which could contain both types of class, Base and Minesweeper. To do this you can't store the objects themselves in the array, because the two types of object might be different size and have different members. So you can have a vector of pointers to the Base class. Then the polymorphism part is for identifying, when you dereference one of those pointers, whether you're pointing to a Base or a Minesweeper. The virtual function is for calling the right function depending on which object it is.
You can't just pass a vector of derived class objects to a function who need a vector of of base class objects, because vector is not derived from vector.
You can do some covertion, get a slice of vector, like this:
vector<Base> converted(base_vec.begin(), base_vec.end());
But this is not efficient, if the calling method is in your control, you can just use template:
template <typename T>
void foo(const vector<T>& v) {
v[0].bar(); // do something with v
}
If you do not want other types those have bar but is not the derived class of Base, you can use std::enable_if:
template<typename T, typename Enable=std::enable_if<std::is_base_of<Base, T>::value>>
void foo(const std::vector<T>& v) {
v[0].bar(); // do something with v
}
Whole program can compile with gcc main.cc -std=c++11:
#include <vector>
class Base{
public:
void bar() const {}
};
class Derived: public Base{
};
template<typename T, typename Enable=std::enable_if<std::is_base_of<T, Base>::value>>
void foo(const std::vector<T>& v) {
v[0].bar();
}
int main() {
std::vector<Derived> a(1);
foo(a);
}
You can also use std::transform with std::back_inserter, see [https://stackoverflow.com/a/33522799/638048]

C++ Invalid use of non-static data member

I wanted to pass-in functions as arguments to a templated function without having any indirection. To achieve this I created two nested structs, each defining the function I wish to pass in to the templated function. Each of the structs accesses data members from the outside class B:
namespace A{
class B{
public:
B();
template <typename T>
void templatedFunction(T t){
//I pass one of the struct objects in to here, to invoke the desired function
t();
}
private:
struct X{
void operator(){
do();
}
void do(){
//Accesses the data members of class B
e->doSomething();
}
};
struct Y{
void operator(){
do();
}
void do(){
//Accesses the data members of class B
d.doSomething();
}
};
C* c;
D d;
E* e;
};
}
and the compiler errors I get are pretty much all of the format:
error: invalid use of non-static data member B::d
for the lines within the struct accessing the class data members and on the lines declaring the data members in B.
A nested class in C++ does not (automatically) have access to an instance of the containing class. It's just a class definition like any other. You need a B instance to access non-static data members of B.
You can restructure your nested class Y as
struct Y
{
void operator()( B& b ){
do( b );
}
void do( B& b ){
//Accesses the data members of class B
b.d.doSomething();
}
};
and fix your function template and calls, and class X, accordingly.
Note that your presented code for operator(), with no argument list, would not have compiled, but I'm not downvoting since you are stopped by another compilation error (i.e., possibly it is the real code you're showing).
If you have a struct (or class for that matter) nested in another class, it it not treated specially in any way. It works exactly the same as if the struct was defined outside of the enclosing class. The only thing which is different is the scope of nested class name. So, if you have
class A { class B{}; };
and
class B{}; class A {};
the only difference is that outside class A you need to name the class B as A::B in the first case, and just B in the second class. There is no other difference, and in particular class B does not gain any special access to class A members.

C++ instantiate function template as class member and using "this" pointer

I have two classes (ClassA and ClassB) who both have two methods (compare and converge). These methods work exactly the same way, but these classes are not related polymorphically (for good reason). I would like to define a function template that both of these classes can explicitly instantiate as a member but I'm getting errors because the methods use "this" and when I turn them into a template the compiler throws an error because they're not member functions.
Is this impossible because of that limitation? Or is there some way to use "this" inside of a function template that is not declared as part of a template class. I've done some research and found nothing.
Logic.h
template <class T>
T* compare(const T& t) {
//stuff involving this
}
template <class T>
T* converge(const T& t,bool b) {
//other stuff involving this
}
ClassA.cpp
#include "ClassA.h"
#include "Logic.h"
//constructors
template ClassA* ClassA::compare(const ClassA& t) const;
template ClassA* ClassA::converge(const ClassA& t,bool b) const;
//other methods
classB is similar.
Any help is appreciated!
I believe you can use CRTP here. Here is an example, you can omit the friend declaration in case you can do the compare using only public members:
template<class T>
class comparer
{
public:
T* compare(const T& t)
{
//Use this pointer
bool b = static_cast<T*>(this)->m_b == t.m_b;
return NULL;
}
};
class A : public comparer<A>
{
public:
friend class comparer<A>;
A() : m_b(0)
{
}
private:
int m_b;
};
class B : public comparer<B>
{
public:
friend class comparer<B>;
B() : m_b(0)
{
}
private:
int m_b;
};
int main()
{
A a1,a2;
A* p = a1.compare(a2);
B b1,b2;
B* p1 = b1.compare(b2);
return 0;
}
You can't use this inside non-member function. What you can do is create template function and declare it as a friend of your classA and classB. But classA and classB members that are accessed by template function must have the same names.
template <typename T>
bool compare(const T& t1, const T& t2)
{
return t1.val == t2.val;
}
class A
{
public:
template <typename T>
friend bool compare(const T&, const T&);
bool compare(const A& a)
{
return ::compare(*this, a);
}
private:
int val;
};
A a1, a2;
a1.compare(a2);
What you want is impossible. Member functions must be declared and defined as members. The same goes for member function templates, from which member functions can be instantiated.
But (why) do those functions have to be members? If those functions don't need access to private stuff in these classes, make them free function templates. The whole STL (which, BTW, is but one part of the C++ standard library) is build around non-member functions and achieves a much higher level of abstraction as any OO container lib coming before it ever did.
Contrary to popular believe, non-member functions generally increase encapsulation:
If you're writing a function that can be implemented as either a member or as a non-friend non-member, you should prefer to implement it as a non-member function. That decision increases class encapsulation. When you think encapsulation, you should think non-member functions.