Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

How to find if type expose a operator[]

2 views
Skip to first unread message

info

unread,
Apr 13, 2002, 5:57:10 AM4/13/02
to
Hi,

I have the following question

Is there a way to find out if one type is expose a operator [] or not?

I've been trying the something as:

template< class T >
bool IsHas( )
{
T::TYPE ( T::*test )( ) const = &T::operator[];
return *test != NULL;
}

which doesn't compile

Does anybody know how I can perform such a check?

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]

Graeme Prentice

unread,
Apr 15, 2002, 6:33:23 PM4/15/02
to
On 13 Apr 2002 05:57:10 -0400, in...@nextagestudio.com (info) wrote:

>Hi,
>
>I have the following question
>
>Is there a way to find out if one type is expose a operator [] or not?
>
>I've been trying the something as:
>
>template< class T >
>bool IsHas( )
>{
> T::TYPE ( T::*test )( ) const = &T::operator[];
> return *test != NULL;
>}

This is a template function. With template functions the type T is
determined when you call the function at compile time
e.g.
IsHas<vector<int> >();

and if TYPE is a type declared in type T then you need typename
typename T::TYPE ( T::*test )() etc


>
>which doesn't compile
>
>Does anybody know how I can perform such a check?

Not at runtime you can't. Your code above will fail at compile time
if there is no operator[]
Why would you want to find out at runtime - its too late to decide to
call it - you have to decide that at compile time.

Graeme

Richard Smith

unread,
Apr 16, 2002, 7:36:49 PM4/16/02
to

"Graeme Prentice" <g...@paradise.net.nz> wrote in message
news:moilbugh37rdc5kee...@4ax.com...

> On 13 Apr 2002 05:57:10 -0400, in...@nextagestudio.com (info) wrote:
>
> >Hi,
> >
> >I have the following question
> >
> >Is there a way to find out if one type is expose a operator [] or not?

[ ... ]

> >Does anybody know how I can perform such a check?
>
> Not at runtime you can't.

Yes you can, although your compiler might not be aware of this ;-). The
following code will do it

template <class T>
class has_subscript_operator
{
private:
typedef char (&yes)[3];
typedef char (&no)[23];
template <size_t> struct helper {};
template <class U> static yes foo( helper<sizeof( &U::operator[] )> * );
template <class U> static no foo( ... );
public:
enum { value = sizeof(foo<T>(0)) == sizeof(yes) };
};

// Usage:
std::cout << has_subscript_operator< my_class >::value << std::endl;


It is possible to write a version of this that actually compiles in current
compiles, but it's rather messy.

--
Richard Smith

info

unread,
Apr 17, 2002, 7:27:13 PM4/17/02
to
"Richard Smith" <ric...@ex-parrot.com> wrote in message news:<1018969434.13641....@news.demon.co.uk>...

On which compiler did you try this ?
Are you sure that it will work ?

info

unread,
Apr 18, 2002, 5:39:06 AM4/18/02
to
Richard,

Isn't more correct solution for this to be the following:

template< typename T >


class has_subscript_operator
{
private:
typedef char (&yes)[3];
typedef char (&no)[23];
template< size_t > struct helper {};

template< typename U > static yes foo( helper< sizeof( &U::operator[](0) ) > * );
template< typename U > static no foo( ... );


public:
enum { value = sizeof(foo<T>(0)) == sizeof(yes) };
};

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Graeme Prentice

unread,
Apr 18, 2002, 9:57:47 AM4/18/02
to
On 16 Apr 2002 19:36:49 -0400, "Richard Smith" <ric...@ex-parrot.com>
wrote:

>
>template <class T>
>class has_subscript_operator
>{
>private:
> typedef char (&yes)[3];
> typedef char (&no)[23];
> template <size_t> struct helper {};
> template <class U> static yes foo( helper<sizeof( &U::operator[] )> * );
> template <class U> static no foo( ... );
>public:
> enum { value = sizeof(foo<T>(0)) == sizeof(yes) };
>};
>
>// Usage:
>std::cout << has_subscript_operator< my_class >::value << std::endl;

Wow - more template tricks I didn't know. The Borland compiler gets
internal compiler errors. The Comeau compiler compiles the code ok
but gave the "wrong" answer.

I spent a while fiddling with it and it seems happy to choose "yes
foo( .. sizeof(U) ... ) but when accessing a member of U is
involved, it fails to find a match for foo<T>(0) ( if I comment out
"no foo ... " )

As you said, its messy - but interesting.

Graeme

[ to moderator - I posted this before but it didn't turn up yet other
posts I sent after it, have turned up so I am reposting this - my
apologies if it turns up twice ]

{ There are time warps. If you get a tracking number, ask us about
the status. If you do not, assume it got lost getting to us. The
assumption may be wrong and it could show up months later. :) -mod/jep

Graeme Prentice

unread,
Apr 18, 2002, 3:06:52 PM4/18/02
to
On 16 Apr 2002 19:36:49 -0400, "Richard Smith" <ric...@ex-parrot.com>
wrote:

>


>template <class T>
>class has_subscript_operator
>{
>private:
> typedef char (&yes)[3];
> typedef char (&no)[23];
> template <size_t> struct helper {};
> template <class U> static yes foo( helper<sizeof( &U::operator[] )> * );
> template <class U> static no foo( ... );
>public:
> enum { value = sizeof(foo<T>(0)) == sizeof(yes) };
>};
>
>// Usage:
>std::cout << has_subscript_operator< my_class >::value << std::endl;
>
>
>It is possible to write a version of this that actually compiles in current
>compiles, but it's rather messy.

Wow - more template tricks I didn't know. The Borland compiler gets


internal compiler errors. The Comeau compiler compiles the code ok
but gave the "wrong" answer.

I spent a while fiddling with it and it seems happy to choose "yes
foo( .. sizeof(U) ... ) but when accessing a member of U is
involved, it fails to find a match for foo<T>(0) ( if I comment out
"no foo ... " )

As you said, its messy - but interesting.

Graeme

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Richard Smith

unread,
Apr 19, 2002, 11:53:36 AM4/19/02
to

"info" <in...@nextagestudio.com> wrote in message
news:50dc3483.0204...@posting.google.com...

> Richard,
>
> Isn't more correct solution for this to be the following:
>
> template< typename T >
> class has_subscript_operator
> {
> private:
> typedef char (&yes)[3];
> typedef char (&no)[23];
> template< size_t > struct helper {};
> template< typename U > static yes foo( helper< sizeof(
&U::operator[](0) ) > * );
^^^

The only non-cosmetic difference I can see is the presence of this (0). I
really don't think that it is legal to have this here. What is it supposed
to do? Did you mean

(((U*)0)->*&U::operator[])(0)

or perhaps

(*((U*)0))[0]

?

If so, then these are valid possibilities, but do something slightly
different. My code tests for an operator[] of *any* signature (although it
will probably fail in the presence of overloads -- I must think that aspect
out more fully), these two alternatives test for the presence of an
operator[] that takes an intergral (or convertable from integral) argument.
Both would have their uses, but do different things.

> template< typename U > static no foo( ... );
> public:
> enum { value = sizeof(foo<T>(0)) == sizeof(yes) };
> };


--
Richard Smith

Richard Smith

unread,
Apr 19, 2002, 11:54:32 AM4/19/02
to

"Graeme Prentice" <g...@paradise.net.nz> wrote in message
news:r0rqbug9k7l0omq3n...@4ax.com...

> Wow - more template tricks I didn't know. The Borland compiler gets
> internal compiler errors. The Comeau compiler compiles the code ok
> but gave the "wrong" answer.

Yes. To my knowledge there are no compilers that are yet up to the
challenge.

> I spent a while fiddling with it and it seems happy to choose "yes
> foo( .. sizeof(U) ... ) but when accessing a member of U is
> involved, it fails to find a match for foo<T>(0) ( if I comment out
> "no foo ... " )

The problem (with Comeau at least) is that as far as I can tell, it doesn't
properly obey the letter of the rules for function overloading. If you're
interested in more examples see the "is_enum<T> ATTN: Andrei Alexandrescu
and ilk" thread here and the "14.8.2 Clarification?" thread on comp.std.c++,
mid to late last month.

--
Richard Smith

Richard Smith

unread,
Apr 19, 2002, 12:00:01 PM4/19/02
to

"info" <in...@nextagestudio.com> wrote in message
news:50dc3483.02041...@posting.google.com...

[ compile time testing for operator[] ]

> On which compiler did you try this ?

Many. None of which were up to the challenge.

> Are you sure that it will work ?

I'm fairly sure that the idea is legal. It's possible that there are errors
in my code -- after all, I couldn't compile it. If you're after a version
that does compile, then the following works in Comeau 4.2.45.2 but only
tests for a particular signature operator[], in this case int
operator[](unsigned) const. Attempts to abstract the required signature of
the operator[] caused Comeau to seg fault ;-(.

namespace details
{
template <class T, int (T::*)(unsigned) const>
struct type_fwd
{
typedef T type;
};


template <class T, class U>
struct has_subscript_helper
{
enum { value = false };
};

template <class T>
struct has_subscript_helper
<T, typename type_fwd<T, &T::operator[]>::type>
{
enum { value = true };
};
}

template <class T>
struct has_subscript_operator
: public details::has_subscript_helper<T, T>
{};

struct foo
{};

struct bar
{
int operator[](unsigned) const;
};

template <bool> struct static_assert;
template <> struct static_assert<true> {};

int main()
{
static_assert< ! has_subscript_operator<foo>::value >();
static_assert< has_subscript_operator<bar>::value >();
}

--
Richard Smith

0 new messages