Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ template class operator overloading with the same signatures

A simple C++ OO question regrading templates and operator overloading: In the following class, I have overloaded the index operator twice:

template<class A, class B>
class test
{
  A a1;
  B a2;
public:
  A& operator[](const B&);
  B& operator[](const A&);
};

Now, if I instantiate an object of this template class with the same typenames:

test<int, int> obj;

calling the index operator will result in an error, because the two overloaded functions will have the same signatures.

Is there any way to resolve this issue?

Sorry, if this is a basic question. I am still learning!

like image 794
user3112666 Avatar asked Jan 09 '19 12:01

user3112666


2 Answers

You can add a partial specialization:

template<class A>
class test<A, A>
{
  A a1, a2;
public:
  A& operator[](const A&);
};
like image 149
xskxzr Avatar answered Oct 07 '22 10:10

xskxzr


You can avoid this issue and make the code more robust and expressive by converting the index to some other type that clarifies what the user wants. Usage would be like this:

bidirectional_map<int, int> myTest;
int& valueFor1 = myTest[Key{1}];
int& key1 = myTest[Value{valueFor1}];

Implemented like this:

template<class TKey>
struct Key { const TKey& key; };

template<class TValue>
struct Value { const TValue& value; };

// Deduction guides (C++17), or use helper functions.
template<class TValue>
Value(const TValue&) -> Value<TValue>;
template<class TKey>
Key(const TKey&) -> Key<TKey>;

template<class TKey, class TValue>
class bidirectional_map
{
  TKey a1;   // Probably arrays
  TValue a2; // or so?
public:
  TValue & operator[](Key<TKey> keyTag) { const TKey & key = keyTag.key; /* ... */ }
  TKey & operator[](Value<TValue> valueTag) { const TValue& value = valueTag.value; /* ... */ }
};

Now, Key and Value are popular names so having them "taken up" by these auxiliary functions is not the best. Also, this is all just a pretty theoretical exercise, because member functions are of course a much better fit for this task:

template<class TKey, class TValue>
class bidirectional_map
{
  TKey a1;   // Probably arrays
  TValue a2; // or so?
public:
  TValue& getValueForKey(const TKey& key) { /* ... */ }
  TKey& getKeyForValue(const TValue& value) { /* ... */ }
};
like image 32
Max Langhof Avatar answered Oct 07 '22 10:10

Max Langhof