templated operators for arrays and pointers

P

__PPS__

suppose I have class that has templated operator[].
I want to have a few overloads/template specializations for different
types. Basicly, the biggest problem I have is to be able to have this:

const char a[] = "this is passed as an array";
const char *p = "this is passed by the address";
x_class x;
x[a] = .. whatever ..;
x[p] = ..;

then x[a] and x[p] call different overloads. For example inside of the
operator[](...) I want to get the length/size of the passed string. In
case if an array is used it's size is known at compile time and with
pointer I need to calculate the length.

I have a solution, but I'm looking for a better example on how to do
this (Note - it should be templated operator[] and not overloads of
functions or operator())


My solution: (a working example of what I mean)
/////////////

#include <iostream>
#include <cstring>
using namespace std;

class x_class{
template<class T>struct size_of{
static inline size_t value(const T &t){
cout << "dynamic version used" << endl;
return strlen(t);
}
};
template<class T, size_t N>struct size_of<T[N]>{
template<class C>static inline size_t value(const C &){
cout << "static version used" << endl;
return sizeof(C) - 1;
}
};

public:
template<class T>void operator[](const T &t)const{
const char *str = &t[0];
size_t len = size_of<T>::value(t);
(cout << "passed string => \"").write(str,len) << "\"\n\n";
}
};


int main(int,char*[]){
const char a[] = "this is passed as an array";
const char *p = "this is passed by the address";
x_class x;
x[a]; //length known at compile time
x[p]; //length is calculated at runtime
x["some other string"]; //known at compile time
}

////////


PS I'm also interested to have operator[](int) and operator[](int []
and int *)
and there must be no confusion if I use x[0] (eg const char* or int??)


thanks
 
V

Victor Bazarov

__PPS__ said:
[...]
and there must be no confusion if I use x[0] (eg const char* or int??)

There should be no confusion to a C++ programmer: the type of 0 is 'int'.

I'll think a bit more about your other questions.

V
 
P

__PPS__

for me it's clear if I call operator[](0), operaor[](size_t) should be
used, but 0 is also a pointer, so there's ambiguos function call if
both operator[](void* or char*) and op[](size_t) are defined.
there's no problem in this case if I do operator[](size_t)0), or
if there's nontemplated version of opearator[](size_t) overload, and
op[] is templated for pointer type (that was my workaround when I had
op[](size_t) and op[](const char*) at the same time and somewhere in
code I had x[0], which gave error (I think both in gcc and vc71); In
that case I rewrote overload for operator[](const char*) as
template<class T>op[](const T*) and it worked)

check by adding to x_class:
void operator()(size_t i){ cout << "operator()(size_t)\n"; }
void operator()(const char *i){ cout << "operator()(const char *)\n";
}
then x[0] is compilation error;
if you change op()(const char*) into:
template<class T>void operator()(const T *i){ cout <<
"operator()(const char *)\n"; }
tjen x[0] calls size_t version without errors
 
V

Victor Bazarov

__PPS__ said:
for me it's clear if I call operator[](0), operaor[](size_t) should be
used,

Why is it clear? '0' is an "int", not a "size_t". 'int' -> 'size_t'
is a standard integral conversion, which has the same rank as the
conversion from '0' to a pointer (13.3.3.1.1/3).
> but 0 is also a pointer,

No, it is NOT. It's a literal of type 'int'.
> so there's ambiguos function call if
both operator[](void* or char*) and op[](size_t) are defined.

Yes. Integral conversions and pointer conversions have the same rank.
there's no problem in this case if I do operator[](size_t)0), or
if there's nontemplated version of opearator[](size_t) overload, and
op[] is templated for pointer type (that was my workaround when I had
op[](size_t) and op[](const char*) at the same time and somewhere in
code I had x[0], which gave error (I think both in gcc and vc71); In
that case I rewrote overload for operator[](const char*) as
template<class T>op[](const T*) and it worked)

check by adding to x_class:
void operator()(size_t i){ cout << "operator()(size_t)\n"; }
void operator()(const char *i){ cout << "operator()(const char *)\n";
}
then x[0] is compilation error;
if you change op()(const char*) into:
template<class T>void operator()(const T *i){ cout <<
"operator()(const char *)\n"; }
tjen x[0] calls size_t version without errors

Don't use 'size_t'. Use 'int'.

V
 
P

__PPS__

the best solution I found uses enable_if, mpl, and type_traits from
boost:

void operator[](const int i)const{
cout << "[int]\n";
}
void operator[](const std::string &s)const{
cout << "[std::string]\n";
}
template<size_t N>void operator[](const char (&t)[N])const{
cout << "[array of " << N << " elements]\n";
}
template<class T>
typename enable_if<
mpl::and_ said:
> >::type operator[](const T t)const{
cout << "[pointer]\n";
}


now it correctly calls array version, pointer, integer or any other
supplied overload (as with string&)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,143
Latest member
SterlingLa
Top