0

I need to create an adapter C++ class, which accepts an integer index, and retrieves some types of data from a C module by the index, and then returns it to the C++ module.

The data retrieving functions in the C module are like:

int getInt(int index);
double getDouble(int index);
const char* getString(int index);
// ...and etc.

I want to implement an array-like interface for the C++ module, so I created the following class:

class Arguments {
public:
    template<typename T> T operator[] (int index);
};

template<> int Arguments::operator[] (int index) { return getInt(index); }
template<> double Arguments::operator[] (int index) { return getdouble(index); }
template<> std::string Arguments::operator[] (int index) { return getString(index); }

(Template class doesn't help in this case, but only template member functions)

The adapter class is no biggie, but calling the Arguments::operator[] is a problem!

I found out that I can only call it in this way:

Arguments a;
int i = a.operator[]<int>(0);       // OK
double d = a.operator[]<double>(1); // OK

int x = a[0];                       // doesn't compile! it doesn't deduce.

But it looks like a joke, doesn't it?

If this is the case, I would rather create normal member functions, like template<T> T get(int index).

So here comes the question: if I create array-operator-overloading function T operator[]() and its specializations, is it possible to call it like accessing an array?

Thank you!

6
  • 4
    Does this answer your question? overload operator[] on return type Commented Nov 17, 2020 at 13:26
  • 1
    If there is no way to deduce the T, then you must provide what T is. Assign the return value to something does not deduce what T is, so you must provide it. Commented Nov 17, 2020 at 13:31
  • overloading operators sometimes isnt as fun as one would like. If you don't like the syntax of the operator use a named method Commented Nov 17, 2020 at 13:51
  • 1
    meh, just after writing the answer I realized that the proposed dupe has a very similar answer. This is a duplicate, but I don't want to hammer it :/ please someone else do it Commented Nov 17, 2020 at 14:07
  • @Botje yes, thank you very much. that post does answer my question. it provided the same solution as idclev provided in this thread. so many smart people :) Commented Nov 17, 2020 at 14:42

1 Answer 1

2

The simple answer is: No, not possible. You cannot overload a function based on its return type. See here for a similar quesiton: overload operator[] on return type

However, there is a trick that lets you deduce a type from the lhs of an assignment:

#include <iostream>
#include <type_traits>

struct container;
struct helper {
    container& c;
    size_t index;
    template <typename T> operator T();
};

struct container {
    helper operator[](size_t i){
        return {*this,i};
    }
    template <typename T> 
    T get_value(size_t i){
        if constexpr (std::is_same_v<T,int>) {
            return 42;
        } else {
            return 0.42;
        }
    }
};

template <typename T> 
helper::operator T(){
    return c.get_value<T>(index);
}

int main() {
    container c;
    int x = c[0];
    std::cout << x << "\n";
    double y = c[1];
    std::cout << y ;
}

Output is:

42
0.42

The line int x = c[0]; goes via container::get_value<int> where the int is deduced from the type of x. Similarly double y = c[1]; uses container::get_value<double> because y is double.

The price you pay is lots of boilerplate and using auto like this

auto x = c[1];

will get you a helper, not the desired value which might be a bit unexpected.

Sign up to request clarification or add additional context in comments.

3 Comments

ahahaha!! beautiful! I gave it a try and it worked. to be honest, when I posted the question, "no way" is the expected answer. as I understand your solution, the type deduction doesn't work for return type but works for conversion operator. so you let the operator[] always returns a delegate object which exposes an operator T(). in this way, you make the type deduction possible. smart! thanks.
@Zhou I have to admit, it is something I never used in production. Its interesting that something like this is possible, but for what I do daily this is a bit too "clever"
hm... yo're right. when I was working in an IBM middleware team many years ago, we just used "C with classes". No clever tricks at all. But now I am creating my own stuff in Github, so..."we're here for a reason, to have fun" :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.