2

Is it possible to write a template function for which a particular type of classes have some functions or overloaded operators? For instance

template <typename T>
void dosomething(const T& x){
    std::cout << x[0] << std::endl;
}

In this context I'm assuming that x is a class that behaves like an array, that is, I have overloaded the [] operator as well as the << so that it can work with std::cout.

The actual code that I have is slightly different but gcc is giving me

error: subscripted value is neither array nor pointer

This must be because it doesn't know that I'm expecting T to be of some class that overloads the [] operator. Does anyone know if it is possible to overcome this? I'd like to let c++ know that the particular type T will have the [] overloaded.

jmlopez
  • 4,603
  • 3
  • 36
  • 72
  • You could try and make a typetrait that checks for the existence of member functions. The [pretty printer](http://stackoverflow.com/questions/4850473/pretty-print-c-stl-containers) features a selection of such typetraits. If you're happy with `*begin()` rather than `[0]`, you can use it right out of the box. – Kerrek SB Aug 24 '11 at 16:37
  • 1
    Did you declare the operator override method `const`? – Jack Edmonds Aug 24 '11 at 16:37
  • Show the actual code. If you are passing an object that overloads operator[], then you shouldn't be getting that error. – Benjamin Lindley Aug 24 '11 at 16:38
  • @Jack, I did it like this: `T& operator[] (CIX i) {return _pt[i];} T operator[] (CIX i) const {return _pt[i];}`. In any case, there might be other types that overloaded the operator and I'm expecting the function to handle this type of objects. – jmlopez Aug 24 '11 at 16:38
  • @Benjamin, I know that I shouldn't be getting this error. It would work fine if C++ knows of the definition. The problem is that the program won't know of its existence until later on. Someone else might create another class that overloads that operator and I want my function to be able to handle it. – jmlopez Aug 24 '11 at 16:41
  • @jmlopez You did mark the parameter as `const` so any methods you call on that object must be `const` as well. Therefore, you can still handle any type of object that overloads that operator as long as the operator is marked `const`. – Jack Edmonds Aug 24 '11 at 16:41
  • @jmlopez It looks like your method declaration doesn't specify the method as `const`. – Jack Edmonds Aug 24 '11 at 16:43
  • @MrLunchtime, sorry, CIX is a macro. `#define CIX const unsigned int&`. – jmlopez Aug 24 '11 at 16:44
  • 1
    @jmlopez: Your function can handle any class that defines a const operator[] that returns a streamable value: http://codepad.org/3rpXoHdf – Benjamin Lindley Aug 24 '11 at 16:46
  • This facility is not available in C++, and still not in C++0x. CONCEPTS have been postponed (http://en.wikipedia.org/wiki/Concepts_(C%2B%2B)) – Ajay Aug 24 '11 at 17:50

4 Answers4

5

You might need to provide a little more detail, as this short example works for me:

#include <iostream>
#include <vector>

template <typename T>
void dosomething(const T& x){
    std::cout << x << std::endl;
}

template <typename T>
void dosomething_else(const T& x){
    std::cout << x[0] << std::endl;
}

int main() {
    dosomething< int >(1) ;
    std::vector< int > vec( 3, 1 );
    //dosomething< std::vector< int > >(vec);
    dosomething_else< std::vector< int > >(vec);
}

However, if you were to uncomment this line you would get a compiler error as std::vector doesn't implement the << operator:

//dosomething< std::vector< int > >(vec);

When you say this your thinking is on the right track:

I'd like to let c++ know that the particular type T will have the [] overloaded.

However, the C++ compiler will actually search for [] operator at compile-time for any functions that request it. If there is no [] operator defined, you will get a compiler error. For example, this will cause a compiler error if inserted into the main() function:

dosomething_else< int >(1);

You get this error message, similar to what you suggest in the question:

test.cpp: In function 'void dosomething_else(const T&) [with T = int]':
test.cpp:19:   instantiated from here
test.cpp:11: error: subscripted value is neither array nor pointer

You can actually check if the [] exists at compile-time using the method outlined in this question: How to check whether operator== exists?

Community
  • 1
  • 1
James Thompson
  • 43,044
  • 17
  • 61
  • 80
  • It seems that I do need to provide more details... I'll edit once I make a more concrete example. – jmlopez Aug 24 '11 at 16:50
  • James, Thank you for your helpful answer. Turns out that the mistake I was making was the order in which I defined the templates and the overloaded functions. For this reason it didn't find the definition of my overloaded operator. Here is the [link](http://stackoverflow.com/questions/7181153/templates-function-overloading-and-their-order-of-appearence) to the other question I posted. – jmlopez Aug 29 '11 at 16:03
4

Make sure the method that declares the operator overload is marked const.

Jack Edmonds
  • 28,069
  • 16
  • 60
  • 77
0

You can either:

1) define a simple class that has [] overloaded, inherit from it, and use that as the argument type instead of T.

2) cast the argument to some type that has your implementation of []

lettucemode
  • 422
  • 4
  • 14
-1

Instead of x[0] use x.operator[](0).

It won't be enough to overload operator << for class T, you'll have to do it for the type that operator [] returns.

Mark Ransom
  • 271,357
  • 39
  • 345
  • 578
  • @Ajay, the question was specifically about a class that overrides `operator[]`. Don't make up requirements that aren't in the question. – Mark Ransom Aug 24 '11 at 22:38
  • First thing I didn't downvoted you. Secondly template should be generic, so assuming that target type is class is wrong assumption. – Ajay Aug 25 '11 at 02:48