Ответ 1
Вы можете использовать одно из следующих действий:
foo(x + 0);
foo(+x);
foo(&x[0]); // assuming operator& has not been overloaded for T
foo(std::addressof(x[0])); // since C++11
Каков наиболее сжатый и идиоматический способ явного разложения массива в указатель?
Например, рассмотрим случай, когда вам нужно руководствоваться SFINAE или быть явным о перегрузке:
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);
Вы можете использовать одно из следующих действий:
foo(x + 0);
foo(+x);
foo(&x[0]); // assuming operator& has not been overloaded for T
foo(std::addressof(x[0])); // since C++11
Самый лаконичный и идиоматический? Я бы сказал, беря адрес первого элемента
foo(&x[0]);
Так как С++ 11 существует стандартный способ, говорящий выше:
auto a = std::addressof(x[0]); // a will be * to int
adressof
имеет следующую подпись
template<class T> T* addressof(T& arg);
и получает фактический адрес объекта или функции arg, даже при наличии перегруженного оператора &
Другая идея (которая также имеет преимущество выше) заключалась бы в написании
auto a = std::begin(x); // a will be * to int
дополнительно это работает с массивами неполных типов, потому что не требует применения [0]
Так как С++ 14 существует еще более явная функциональность: std::decay
Запасы &x[0]
всегда были для меня неудобными, потому что массив, о котором идет речь, может быть массивом неполных типов, и, конечно, недействительно применять оператор индекса к одному. Вместо этого рассмотрим это,
foo(&*x);
это всего лишь один тип символов, чем foo(+x)
, который гораздо менее читабельен и сложнее выполнить.