Hello

i am working on a little project called an Accociation class. It is a bi-direction association, i.e. if "dog" is associated with "canine", then automatically "canine" is also associated with "dog".

The core of the class is two map objects, a left-to-right and a right-to-left map.

Here is a small (very simplistic) snippet to illustrate my problem:

template<class T1, class T2>
	class Different 
	{
	public:
		Different(const pair<T1,T2> & somePair)
		{
			leftToRight.insert(somePair);  
			rightToLeft.insert(pair<T2, T1>(somePair.second, somePair.first)); 
		}
		virtual T1 find(const T2 & lookupValue)
		{
			return rightToLeft[lookupValue]	;
		}
		virtual T2 find(const T1 & lookupValue)
		{
			return leftToRight[lookupValue]	;
		}
	private:
		map<T1,T2> leftToRight;
		map<T2,T1> rightToLeft;
	};

The class works fine as long as T1 and T2 are not the same. If they are then both the "find" methods are the same and hence the C2253 error.
So here is what I have done:

1. Make a virtual base class called VirtualClass, with the first "find" method defined virtually.
2. Derive class Different from VirtualClass
3. Make a second derivation, call Same, which is slightly different to the Differnt class, but with only one definition of "find" so that it works if T1 and T2 are the same (see below)
4. Make an Accessor class. (I hope that accessor class doesn't mean something else, I kinda invented the word on the fly ;))

The accessor class, called Association has all the same constructors as Different and Same, but only one member variable, called virtualClass , which is a pointer to the base class VirtualClass.
The idea is that if T1 and T2 are the same, it will point to Same, else it points to Different.
If the user needs to "find" something, he will simply type in something like

someClass lookupValue = ...;
Association<someClass, anotherClass> myAssociation;

anotherClass lookupResult = myAssociation.virtualClass->find(lookupValue);

I think my plan is quite legitimate, but naturally the compiler doesn't :$ (V100, I think), and throws error C2253.

Here is all the code of what I am trying to do:

#include <map>
#include <string>
#include <iostream>
#include <typeinfo>

using namespace std;

template<class T1, class T2> bool sameType()
{
	if (strcmp(typeid(T1).name(), typeid(T2).name()) == 0)
		return true;
	return false;
}
template<class T1, class T2>
	class VirtualClass
	{
	public:
		virtual T1 find(const T2 & lookupValue) =  0;
	};
template<class T1, class T2>
	class Different : public VirtualClass<T1, T2>
	{
	public:
		Different(const pair<T1,T2> & somePair)
		{
			leftToRight.insert(somePair);  
			rightToLeft.insert(pair<T2, T1>(somePair.second, somePair.first)); 
		}
		virtual T1 find(const T2 & lookupValue)
		{
			return rightToLeft[lookupValue]	;
		}
		virtual T2 find(const T1 & lookupValue)
		{
			return leftToRight[lookupValue]	;
		}
	private:
		map<T1,T2> leftToRight;
		map<T2,T1> rightToLeft;
	};
template<class T1, class T2>
	class Same : public VirtualClass<T1, T2>
	{
	public:
		Same(const pair<T1,T2> & somePair)
		{
			dataMembers.insert(somePair);  
			dataMembers.insert(pair<T2, T1>(somePair.second, somePair.first)); 
		}
		virtual T1 find(const T2 & lookupValue)
		{
			return dataMembers[lookupValue]	;
		}
	private:
		map<T1,T1> dataMembers;
	};

template<class T1, class T2>
	class Association
	{
	public:
		Association(const pair<T1, T2> & somePair)
		{
			if(sameType<T1,T2>())
				virtualClass = new Same<T1,T2>(somePair);
			else
				virtualClass = new Different<T1, T2>(somePair);
		}
		virtual ~Association()
		{
			delete[] virtualClass;
		}

		VirtualClass<T1, T2> * virtualClass;
	};

int main()
{
	Association<int, double> intDouble(pair<int, double>(1, 13.4));
	Association<int, int> intInt(pair<int, int>(2,5));

	return 1;
}

Any ideas? Please help.

PS. O, I know I should probably just stick with two classes, Different and Same, but it would be so cool if I had only one class to deal with all bi-directional associations.

You could specialize for the same type. Something similar to :

template< class T1, class T2 >
class Different {
    public:
        Different(const std::pair< T1, T2 >& somePair) {
            l2r.insert(somePair);
            r2l.insert(std::make_pair(somePair.second, somePair.first));
        }
        virtual T1 find(const T2& key) { return r2l[key]; }
        virtual T2 find(const T1& key) { return l2r[key]; }
    private:
        std::map<T1,T2> l2r;
        std::map<T2,T1> r2l;
};

template<class T>
class Different<T,T> {
    public:
        Different(const std::pair< T, T >& somePair) {
            table.insert(somePair);
            table.insert(std::make_pair(somePair.second, somePair.first));
        }
        virtual T find(const T& key) { return table[key]; }
    private:
        std::map<T,T> table;
};

That allows for something like

int x, y;
Different<int, int> dInt(std::make_pair(x, y));
// ...
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.