views:

83

answers:

3

Hello,

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!

+1  A: 

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;
}
Naveen
It's useful to give `comparer` a protected non-virtual destructor.
Steve Jessop
A: 

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);
Nikola Smiljanić
A: 

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.

sbi