10

What is the most concise and idiomatic way of explicitly decaying an array into a pointer?


For example, consider the case where you need to be able to guide SFINAE or be explicit about an overload:

template<typename T, std::size_t N> void foo(T(&x)[N]);
template<typename T>                void foo(T *x); 
//
int x[2] = {0, 1};
foo(x);
mockinterface
  • 14,452
  • 5
  • 28
  • 49

3 Answers3

9

You may use one of the following:

foo(x + 0);
foo(+x);
foo(&x[0]); // assuming operator& has not been overloaded for T
foo(std::addressof(x[0])); // since C++11
Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • The center one (as has `&*x`, but not `&x[0]`) has the unique advantage that the array element type doesn't have to be complete, so it works on `struct Foo { static ForwardDeclaredType array[]; };` – Johannes Schaub - litb Apr 11 '14 at 22:41
  • 1
    I like `+x` the best. It’s a convenient way to say “do the usual conversions & promotions”, for example if you want to send a `uint8_t` to an `ostream` as a formatted integer instead of a raw byte. – Jon Purdy May 20 '14 at 04:39
5

The most concise and idiomatic ? I would say taking the address of the first element

foo(&x[0]);

UPDATE

Since c++11 there's a standard way of saying the above:

auto a = std::addressof(x[0]); // a will be * to int

adressof has the following signature

template<class T> T* addressof(T& arg);

and Obtains the actual address of the object or function arg, even in presence of overloaded operator&

Another idea (which also has the advantage of the above) would be to write

auto a = std::begin(x); // a will be * to int

additionally this works with arrays of incomplete types because it requires no application of [0]

UPDATE 2

Since c++ 14 there's even more explicit functionality on this : std::decay

Nikos Athanasiou
  • 29,616
  • 15
  • 87
  • 153
  • @Deduplicator Then you could use `+x` as well. Is that more readable? Easier to understand? – dyp Apr 11 '14 at 12:33
  • @dyp: THe question wanted `concise and idiomatic`. It's no less readable, harder to understand or less idiomatic. Still, not much better than +0 (it has more binding power though). Less concise than unary plus... – Deduplicator Apr 11 '14 at 12:41
  • 1
    @Deduplicator For an array I think `&x[0]` is easier to read, and can be extended to apply to any class that provides an `operator[]` method (and if it doesn't supply an `operator*`, then `&*c` won't work. Perhaps on a `std:vector`, or `std:array`?). If you say `&*c`, I'm thinking that `c` is an iterator of some sort, or some sort of proxy object and I'm trying to get the address of the actual object. – Andre Kostur Apr 11 '14 at 14:01
  • It looks quite good, just for the last one (std::begin) you still have to add `&*`, because it yields an iterator (which need not be a pointer). But just as you argue that there are some containers not providing `operator*`, there are some smart-pointers not providing `operator[]`. So, `&*p` and `&p[0]` are of equal worth, I personally preferring the first. – Deduplicator Apr 27 '14 at 01:35
2

The stock &x[0] always felt awkward to me because the array in question can be an array of incomplete types, and it is of course invalid to apply a subscript operator to one. Consider this instead,

foo(&*x);

this is only one more characters to type than foo(+x) which is far less readable and harder to grok.

mockinterface
  • 14,452
  • 5
  • 28
  • 49
  • 1
    To clarify, `[0]` can be used on an incomplete array type (whose elements are complete types); but not on an array of incomplete types. – M.M Apr 12 '14 at 01:41
  • Additionally, if one works with zero array length *extensions*, traversing through `x[0]` to obtain the address is notionally wrong. – mockinterface Apr 12 '14 at 02:20
  • I've seen long debates about whether `&x[0]` and `x+0` are equivalent in C++ (they are in C) for array types; some feel that `&x[N]` should be undefined if `N` is the length. – M.M Apr 12 '14 at 02:24
  • @MattMcNabb Agree, if one argues that `&x[N]` is undefined for some values of `N` why go there at all and start to distinguish between valid and invalid lengths, instead of just doing `&*x` working with `x` the type itself directly. – mockinterface Apr 12 '14 at 02:30
  • @mockinterface What if `x` is an array of types that overload the `&` operator ? You can check my answer for two solutions on this – Nikos Athanasiou Apr 26 '14 at 22:21
  • @NikosAthanasiou Thanks for your effort Nikos, but I think you rather contradict yourself - your real answer employs '&' so it is subject to the same problem of overloading (and overloading address-of is rather far-fetched and very rare), and while I appreciate that you mentioned the standard ways - they are not concise, and I think that `&*x` is better than `&x[0]` for the reasons I gave in my answer. – mockinterface Apr 28 '14 at 10:22