13

In C++ one can add implicit-conversion operators in a class or struct. For instance, 3D vector types usually include something like:

struct Vector {
    float x, y, z;
    operator float * () { return reinterpret_cast<float *>(this); }
};

to allow accessing the vector's elements with subscripts, passing to functions that want a pointer, etc. It occurred to me to wonder: can we instead write a conversion operator that returns a reference to array of float, instead of a pointer to float?

(This is of purely academic interest. I don't know what benefits a reference-to-array would have, if any, over a simple pointer.)

As a free function we can do this like:

float (&convert(Vector & v))[3]
{
    return reinterpret_cast<float(&)[3]>(v);
}

Vector v;
convert(v);

However, I haven't been able to find the right syntax to do this as a conversion operator. I've tried things like:

operator float(&)[3] ()
operator float(&())[3]
float (&operator())[3]

and various other permutations, but I just get various syntax errors (g++ 4.8.1).

Is it possible to write a conversion operator returning a reference to array, and if so, what is the syntax to do so?

Nathan Reed
  • 3,583
  • 1
  • 26
  • 33
  • 2
    I would imagine a typedef would work if anything. – chris Dec 01 '13 at 04:27
  • @chris Ahh, yeah, a typedef works! That didn't occur to me. Still, I'd like to know if it can be done "directly". – Nathan Reed Dec 01 '13 at 04:46
  • I would be interested in seeing it done. I do recall something about a typedef/using alias being able to do things that you cannot do without it. – chris Dec 01 '13 at 04:58
  • Does using `identity` count? – uk4321 Dec 01 '13 at 05:42
  • @uk4321, That's an interesting idea, but it still boils down to a type alias :p – chris Dec 01 '13 at 05:43
  • possible duplicate of [operator member\_function\_pointer\_type() without typedef?](http://stackoverflow.com/questions/17130368/operator-member-function-pointer-type-without-typedef) – user541686 Dec 01 '13 at 09:49

2 Answers2

6

In fact you can, you almost had it with the last one:

(&operator float())[3];

As for the question of whether or not a typedef is ever necessary, I think it is from reading the comments on https://stackoverflow.com/a/6755760/2925619 (which answer is what helped me get the syntax for the above as well).

Edit:

Apparently, this syntax is incorrect and returning a reference to an array is forbidden as chris discovered for us. I guess you'll just have to settle for a typedef.

Community
  • 1
  • 1
uk4321
  • 1,028
  • 8
  • 18
  • Very interesting, although the really interesting part is `error: must use a typedef to declare a conversion to 'int (&)[10]'`. Good enough for me! – chris Dec 01 '13 at 06:12
  • @chris hmm, GCC 4.8.1 accepts it. You are using clang? Seems to be a very specific error, I think they must be right. – uk4321 Dec 01 '13 at 06:13
  • Yes, I do on Coliru, and that's probably what Kerrek was referring to in his answer. – chris Dec 01 '13 at 06:15
  • @chris ha, I read the top part and didn't see the bottom half that said it was invalid. My mistake, deleting... – uk4321 Dec 01 '13 at 06:17
  • By all means keep it. It's a good example of how it would be done, were it not presumably explicitly forbidden (which is also a valid answer). – chris Dec 01 '13 at 06:22
  • 1
    Interestingly enough, N3485 § 12.3.2/3 says an array isn't allowed, but not a reference to an array. On the other hand, it does list `conversion-function-id: operator conversion-type-id`, which would, if I'm right, rule out the ampersand to the left of `operator`. – chris Dec 01 '13 at 06:30
  • Cool! Even if this is nonstandard, that's nice to see that g++ allows some syntax for it. – Nathan Reed Dec 01 '13 at 06:58
6

If you are using C++11, the problem may be resolved by introducing the ref/ptr template aliases as defined below:

template<typename T>
using ref = T&;

template<typename T>
using ptr = T*;

With this aliases the declaration of reference to array conversion operator will be in form:

operator ref<float[3]>(); 

Also it make function taking/returning pointer to function/array declaration much cleaner, e.g.:

ptr<int()> foo(ptr<int(int)> bar);

Instead of:

int (*foo(int(*bar)(int)))();