This is a selection of my class
template <typename TValue, typename TPred = std::less<TValue> >
class BinarySearchTree {
public:
BinarySearchTree<TValue, TPred> &operator=(BinarySearchTree<TValue, TPred> const &tree) {
if (this != &tree) {
tree.VisitInOrder(Insert);
}
return *this;
}
bool Insert(TValue const &value) {
return m_Insert(value, pRoot);
}
template <typename TVisitor> void VisitInOrder(TVisitor visitor) const;
...
};
and the following sequence wont work: VisitInOrder(Insert) because my compiler says that there are arguments missing
but my main looks like this and there i can use the function without its arguments:
void Print(int const x) { cout << x << endl; }
int main() {
BinarySearchTree<int> obj1, obj2, obj3;
obj1.Insert(10);
obj1.VisitInOrder(Print);
return 0;
}
full code here: http://pastebin.com/TJmAgwdu
Your function Insert is a member function, which means it accepts an implicit this pointer. You have to use std::bind() if you want to get a unary functor out of Insert():
if (this != &tree) {
tree.VisitInOrder(
std::bind(&BinarySearchTree::Insert, this, std::placeholders::_1));
}
Here is a live example showing the program compiling when the following assignment is present:
obj3 = obj1;
Related
Is it possible to override the -> operator in template class and return something by reference?
I saw this post: Overloading member access operators ->, .*
And there is an example of overriding -> and return by reference, but I can't get this to work with templates. Here's a small example of what I'm trying to achieve:
#include <iostream>
using namespace std;
class A
{
public:
void do_something()
{
cout << "Hey there";
}
};
template<class T>
class Ref
{
public:
Ref(T* ptr)
{
objPtr = ptr;
}
// this is another alternative, but I don't want to write Get() every time I want to access the object
T& get() { return *objPtr; }
template <class T>
Ref<T>& operator->() const { return *objPtr; }
// doesn't work either
//T& operator->() const { return *objPtr; }
// this works as expected, but I really MUST return by reference
//T* operator->() const { return objPtr; }
private:
T* objPtr;
};
int main()
{
A myObj;
Ref<A> ref(&myObj);
// error C2675: unary '->': 'Ref<A>' does not define this operator or a conversion to a type acceptable to the predefined operator
ref->do_something();
return 0;
}
How can this be done?
If you return a reference, you can't use it in ref->do_something(); which requires a pointer. You'd have to use this cumbersome method:
ref.operator->().do_something();
Instead return a pointer - and make it a T* (or const T*), not a Ref<T>*.
Example:
#include <iostream>
class A {
public:
void do_something() {
std::cout << "Hey there\n";
}
};
template<class T>
class Ref {
public:
Ref(T& ptr) : objPtr(&ptr) {} // taking a T& but storing a pointer
const T* operator->() const { return objPtr; }
T* operator->() { return objPtr; }
private:
T* objPtr;
};
int main() {
A myObj;
Ref<A> ref(myObj);
ref->do_something();
}
Considering the following code:
class MyClass
{
...
};
template <typename Object>
class List
{
public:
void insert(const Object & x)
{
// call when Object is MyClass
}
void insert(const Object & x)
{
// call when Object is MyClass*
}
}
int main()
{
MyClass a;
List<MyClass> lst;
List<MyClass*> plst;
lst.insert(a);
plst.insert(new Myclass);
return 0;
}
How to tell the compiler call different methods based on if the template is a class or a pointer?
How to fix the code above?
You can use a combination of std::is_pointer and std::enable_if:
#include <type_traits>
#include <iostream>
class MyClass
{
};
template <typename Object>
class List
{
public:
template<class T=Object>
void insert(T t, typename std::enable_if<std::is_pointer<T>::value >::type* = 0)
{
std::cout << "insert pointer" << std::endl;
}
template<class T=Object>
void insert(T t, typename std::enable_if<!std::is_pointer<T>::value >::type* = 0)
{
std::cout << "insert non-pointer" << std::endl;
}
};
int main()
{
MyClass a;
List<MyClass> lst;
List<MyClass*> plst;
lst.insert(a);
plst.insert(new MyClass());
return 0;
}
Live example: https://ideone.com/CK8Zdo
This will allow you to insert both pointers and non-pointers into a pointer or non-pointer list.
If you want to restrict that, you can use this:
#include <type_traits>
#include <iostream>
class MyClass
{
};
template <typename Object>
class List
{
public:
template<class T=Object>
void insert(T t, typename std::enable_if<std::is_same<T,Object>::value&&std::is_pointer<T>::value >::type* = 0)
{
std::cout << "insert pointer" << std::endl;
}
template<class T=Object>
void insert(const T& t, typename std::enable_if<std::is_same<T,Object>::value&&!std::is_pointer<T>::value >::type* = 0)
{
std::cout << "insert non-pointer" << std::endl;
}
};
int main()
{
MyClass a;
List<MyClass> lst;
List<MyClass*> plst;
lst.insert(a);
// plst.insert(a); // compiler error
// lst.insert(new MyClass()); // compiler error
plst.insert(new MyClass());
return 0;
}
Live example: https://ideone.com/3DtBfr
I'm aware that my answer is not exactly about what you are asking, but maybe it could help.
I believe your intention is to have List class with one insert method (not two of them) and behaviour of this method should depend on your template parameter. For this
you could write a specialization of your class for pointers. Then basic template would be used for non pointer types and specialization would be used for pointer types.
Your code would look like this:
template <typename Object>
class List
{
public:
void insert(const Object & x)
{
// call when Object is MyClass
}
};
template <typename Object>
class List<Object *>
{
public:
void insert(Object * x)
{
// call when Object is MyClass*
}
};
void insert(const Object & x)
{
M_insert(x, dispatcher<std::is_pointer<Object>::value> );
}
Inside List use a dispatcher
template <bool B> class dispatcher {};
using ObjectPtr = dispatcher<true>;
using ObjectValue = dispatcher<false>;
then dispatch to M_insert:
void M_insert(const Object &p, ObjectPtr) { // Object is a pointer }
void M_insert(const Object &p, ObjectValue) { // Object is not a pointer }
Live example here. But, I'd encourage you to determine whether you really need that and possibly fix your design accordingly.
This does the trick:
template <typename Object>
class List
{
public:
template<class C = Object>
void insert(const C & x)
{
// call when Object is MyClass
std::cout << "1" << "\n" ;
}
template<class P = Object*>
void insert(P* p)
{
// call when Object is MyClass*
std::cout << "2" << "\n" ;
}
} ;
Here is a working example.
I have three classes
class A
class B
class C
I have two maps
std::map<A*, B*> myMap1;
std::map<A*, C*> myMap2;
and object pointers of A
A* obj_ptr_A1 = new A; and so on
I want to perform a find_if on both the maps for A*, so I wrote a functor and overloaded operator () twice as follows
class functor
{
private:
A* m_member;
public:
explicit functor(A* input) : m_member(input){}
bool operator()(const std::pair<A*, B*>& iter) const
{
return (m_member->GetValue() == (iter.first)->GetValue());
}
bool operator()(const std::pair<A*, C*>& iter) const
{
return (m_member->GetValue() == (iter.first)->GetValue());
}
};
where GetValue() is a member function of A returning an integer.
Usage:
if(std::find_if(myMap1.begin(), myMap1.end(), functor(obj_ptr_A1)) != myMap1.end())
{
std::cout << "Found in myMap1" << std::endl;
}
if(std::find_if(myMap2.begin(), myMap2.end(), functor(obj_ptr_A1)) != myMap2.end())
{
std::cout << "Found in myMap2" << std::endl;
}
This gives me compilation error
error C3066: there are multiple ways that an object of this type can be called with these arguments
Is this overloading wrong?
Full code is here http://pastebin.com/DnUQKHPp It gives compilation error.
Try the following (Without testing)
template <class T>
class functor
{
private:
A* m_member;
public:
explicit functor(A* input) : m_member(input){}
bool operator()(const std::pair<A*, T*>& iter) const
{
return (m_member->GetValue() == (iter.first)->GetValue());
}
};
if(std::find_if(myMap1.begin(), myMap1.end(), functor<B>(obj_ptr_A1)) != myMap1.end())
{
std::cout << "Found in myMap1" << std::endl;
}
if(std::find_if(myMap2.begin(), myMap2.end(), functor<C>(obj_ptr_A1)) != myMap2.end())
{
std::cout << "Found in myMap2" << std::endl;
}
What I found is that if you make the comparison Argument a template parameter instead of A* you can do different key-value combinations in the map, provided you make the functor::operator() a template for the Iterator.
This is how the functor looks like:
template<typename Argument>
class functor
{
private:
Argument m_member;
public:
functor(Argument a)
:
m_member(a)
{}
template<typename PairIterator>
bool operator()(PairIterator iter) const
{
return (m_member->GetValue() == (iter.first)->GetValue());
}
};
This is the functor generator:
template<typename Argument>
functor<Argument> make_functor(Argument const & a)
{
return functor<Argument>(a);
}
and here is the complete online example.
I have a template class, called Cell, here the definition:
template <class T>
class OneCell
{
.....
}
I have a cast operator from Cell to T, here
virtual operator const T() const
{
.....
}
Now i have derived class, called DCell, here
template <class T>
class DCell : public Cell<T>
{
.....
}
I need to override the Cell's cast operator (insert a little if), but after I need to call the Cell's cast operator. In other methods it's should be something like
virtual operator const T() const
{
if (...)
{
return Cell<T>::operator const T;
}
else throw ...
}
but i got a compiler error
error: argument of type 'const int (Cell::)()const' does not match 'const int'
What can I do?
Thank you, and sorry about my poor English.
You are missing parentheses, so the compiler thought you were trying to return the member function, not call it.
return Cell<T>::operator const T();
You're not actually calling the operator:
return Cell<T>::operator const T();
Full code:
template <class T>
class OneCell
{
public:
virtual operator const T() const
{
return T();
}
};
template <class T>
class DCell : public OneCell<T>
{
public:
virtual operator const T() const
{
cout << "operator called";
return OneCell<T>::operator const T();
}
};
int _tmain(int argc, _TCHAR* argv[])
{
DCell<int> x;
int y = (int)x;
}
Consider this code with the implementations of Cell and DCell:
#include <iostream>
#include <exception>
template<class T>
class Cell
{
protected:
T cnt;
public:
Cell(const T& cnt = T()) : cnt(cnt){}
virtual operator const T() const { return cnt; }
};
bool test_bool = true;
template<class T>
class DCell : public Cell<T>
{
public:
DCell(const T& cnt = T()) : Cell<T>(cnt){}
virtual operator const T() const
{
if(test_bool)
{
return Cell<T>::operator const T(); // Here you had Cell<T>::operator const T;
} else {
throw std::exception();
}
}
};
int main()
{
DCell<int> cell(5);
std::cout << static_cast<int>(cell) << "\n"; // prints 5 (and a new line)
return 0;
}
Don't make the operator virtual. Instead, delegate to a protected virtual helper function.
template <class T>
class Cell
{
public:
operator const T() const { return cvt_T(); }
protected:
virtual const T cvt_T() const;
};
template <class T>
class DCell : public Cell<T>
{
const T cvt_T() const
{
if (...)
{
return Cell<T>::cvt_T();
}
else throw ...
}
};
This and other good practices can be learned from GotW, here is the section on virtual architecture.
As an exercise for my personal enlightenment, I implement vector math with expression templates. I want to implement some operations that apply the same unary function to all elements to a vector expression. So far, I do this.
My base vector expression template is implemented like this
template <typename E>
class VectorExpr {
public:
int size() const { return static_cast<E const&>(*this).size(); }
float operator[](int i) const { return static_cast<E const&>(*this)[i]; }
operator E& () { return static_cast<E&>(*this); }
operator E const& () const { return static_cast<const E&>(*this); }
}; // class VectorExpr
Then, an object supposed to be a vector will look like this
class Vector2 : public VectorExpr<Vector2> {
public:
inline size_t size() const { return 2; }
template <typename E>
inline Vector2(VectorExpr<E> const& inExpr) {
E const& u = inExpr;
for(int i = 0; i < size(); ++i)
mTuple[i] = u[i];
}
private:
float mTuple[2];
};
Let's say I want to apply std::sin to all elements of an expression
template <typename E>
class VectorSin : public VectorExpr<VectorSin<E> > {
E const& mV;
public:
VectorSin(VectorExpr<E> const& inV) : mV(inV) {}
int size() const { return mV.size(); }
float operator [] (int i) const { return std::sin(mV[i]); }
};
Question => If I want to add more functions, I copy-paste what I do for the sin function, for every single function (like cos, sqrt, fabs, and so on). How I can avoid this kind of copy-pasting ? I tried things and figured out I'm still low in template-fu. No boost allowed ^^
template <typename F, typename E>
class VectorFunc : public VectorExpr<VectorFunc<F, E> > {
E const& mV;
public:
VectorSin(VectorExpr<E> const& inV) : mV(inV) {}
int size() const { return mV.size(); }
float operator [] (int i) const { return f(mV[i]); }
// this assumes the Functor f is default constructible, this is
// already not true for &std::sin. Adding the constructor that
// takes f, is left as an exercise ;)
F f;
};
In addition to the answer by pmr, The standard <cmath> functions aren't functors, so you couldn't use them directly to specify unique specialisations of your class - i.e. you wouldn't have a separate template instantiation for std::sin versus std::cos (which is what I gather you're aiming for? correct me if I've misunderstood you on that).
You could create a wrapper in order to map a function pointer to a distinct type, e.g.
#include <iostream>
template< void (*FuncPtr)() > struct Func2Type
{
void operator() () { FuncPtr(); }
};
void Hello() { std::cout << "Hello" << std::endl; }
void World() { std::cout << "world" << std::endl; }
int main()
{
Func2Type<Hello> test1;
Func2Type<World> test2;
test1();
test2();
}
That way you could use them as template arguments in the same way as a normal functor class