1

I am learning about C++ in my spare time, and I am implementing a class that overloads the subscript / [] operators. Now, I wanted to be able to pass two or more arguments to the subscript operators as follows (separated by a comma):

myObject[i,j,...], where the arguments could for instance be strings or ints

I found out that C++ does not allow the subscript operator to accept more than one argument. However, I read about overloading the comma operator in this thread, as an alternative solution to that 'problem'.

In the example, the comma operator is overloaded using very specific signature, with two custom Enum's, but I can see that it's not a good idea to overload the comma operator for general type pairs (which would be my use case).

With my limited knowledge of C++, that made me curious about whether it would be at all possible to limit the 'scope' or use of the comma operator overload to a specific situation or context, e.g, only in the subscript operator overload definition, giving me the functionality I am interested in, without causing interference elsewhere.

Community
  • 1
  • 1
timbit
  • 353
  • 2
  • 11

3 Answers3

1

You cannot restrict regular function/operator to context, but you can restrict it by scope thanks to namespace.

enum class E {A, B};

struct C
{
    int operator [](const std::pair<E, E>& p) const
    {
        return data[static_cast<int>(p.first) * 2 + static_cast<int>(p.second)];
    }
    std::array<int, 4> data{{1, 2, 3, 4}};
};

namespace comma
{
    std::pair<E, E> operator , (E lhs, E rhs) { return { lhs, rhs }; }
}

int main()
{
    C c;

    {
        using namespace comma; // operator , is valid here.

        std::cout << c[E::A, E::B] << std::endl;
        auto p = (E::A, E::B); // but also here :/ p = {E::A, E::B}
        static_cast<void>(p);
    }
    {
        std::cout << c[E::A, E::B] << std::endl; // result in c[E::B]
        auto p = (E::A, E::B); // p = E::B
        static_cast<void>(p);
    }
}

Demo

as alternative, you may use regular method, operator () method (which can take several parameter), use std::pair/std::tuple as argument (that would require extra enclosing {} at call site).

Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • This is cool! Thanks for this. So, using namespaces, I could theoretically also use e.g. `std::pair operator , (int lhs, int rhs) { return { lhs, rhs }; }` within that scope, without mucking up other uses of the comma operator, outside of that scope, right? – timbit May 05 '17 at 10:36
  • `operator,` must have at least one parameter of class or enumeration type. so `int`/`int` would be illegal. – Jarod42 May 05 '17 at 11:13
0

No it is not possible to overload operators for specific contexts only. You can still limit its use based on the types of the operator thou.

jotik
  • 17,044
  • 13
  • 58
  • 123
0

When you overload an operator, you're specifying which types are valid to be used with this operator. So it would be a good idea to design it with the types defined within your class.

class YourClass
{
public:
class YourType{};
};

pair<YourClass::YourType, YourClass::YourType> operator , (YourClass::YourType p1, YourClass::YourType p2)
{
    return make_pair(p1, p2);
}

But if you need some form of generalization, you can use templates and template specialization.

sithereal
  • 1,656
  • 9
  • 16
  • Yes, this is also what the linked example in my question provides. I was just wondering whether it is also possible to do it safely for arguments of general types, but I guess this is not possible. – timbit May 05 '17 at 08:07