интерпретация T (&array)[size] в шаблонах
От: pofig  
Дата: 21.12.11 19:04
Оценка:
Салют.
Объясните плиз как следует понимать конструкцию
T (&array)[length]

используемую в шаблонах:
template<typename T, int length>
void function(T (&array)[length]) {}

Для чего она нужна понятно, а вот что физически происходит и почему нужно писать именно так
не ясно. Для чего обязательно амперсанд и скобочки?
Re: интерпретация T (&array)[size] в шаблонах
От: Сыроежка  
Дата: 21.12.11 19:26
Оценка: 2 (1) +1
Здравствуйте, pofig, Вы писали:

P>Салют.

P>Объясните плиз как следует понимать конструкцию
P>
P>T (&array)[length]
P>

P> используемую в шаблонах:
P>
P>template<typename T, int length>
P>void function(T (&array)[length]) {}
P>

P>Для чего она нужна понятно, а вот что физически происходит и почему нужно писать именно так
P>не ясно. Для чего обязательно амперсанд и скобочки?

Таким образом задается ссылка на массив. В данном случае & — это спецификатор ссылки. В С++ массив в функции можно передавать двумя способами. Если в функции параметр объявлен как массив, например, void f( int a[] ), то при передаче массива имя массива преобразуется в указатель на первый элемент массива. А если вы объявили ссылку на массив в качестве параметра void f( int ( &a )[10] ); то в функцию передасться ссылка на массив. То есть внутри функции вы получите алиас вашего исходного массива, который был задан в качестве аргумента при вызове функции. При этом вся информации о массиве будет сохранена.

Сравните два выражения, которые, допустим, присутствуют в теле указанных функция:
первая функция sizeof( a );
вторая функция sizeof( a );

Длля первой функции резальтат работы оператора будет равен 4 (на 32 битовой платформе) , то есть размеру указателя, так как в первой функции массив, заданный в качестве аргумента функции преобразуется в указатель на первый элемент массива.
Во второй функции результат работы оператора будет равен 40, так как во второй функции вы имеете дело с самим исходным массивов, заданным алиасом, указанным в качестве имени параметра.
Меня можно встретить на www.cpp.forum24.ru
Re: интерпретация T (&array)[size] в шаблонах
От: Kirikaza Россия kirikaza.ru
Дата: 21.12.11 19:27
Оценка: 24 (1) +1
Здравствуйте, pofig, Вы писали:

P>Салют.

P>Объясните плиз как следует понимать конструкцию
P>
P>T (&array)[length]
P>

P>Для чего она нужна понятно, а вот что физически происходит и почему нужно писать именно так
P>не ясно. Для чего обязательно амперсанд и скобочки?

Амперсанд -- чтобы была ссылка на массив, а скобки -- из-за синтаксиса.

Ссылка нужна потому, что получить массив в качестве параметра нельзя; в C поэтому получали указатель на первый элемент:

void f( int * array );

int main() {
    int a[3];
    f(a);
}


Здесь при вызове f() происходит "сведение" (decaying) массива к указателю на первый элемент. Очевидно, что информация о размере потеряна.

Зато можно получить указатель на массив нужного размера, например:
void g( int (*array)[3] );

int main() {
    int a[3];
    g(&a);
}


Сведение здесь не происходит, т.к. передаётся уже указатель на массив.

Зачем здесь скобки -- см. пример ниже:
int* array_of_three_pointers_to_int [ 3 ];
int (*pointer_to_array_of_three_ints) [ 3 ];


Сейчас функция g работает только для массивов из трёх элементов. Обобщаем для любого размера:
template<size_t length>
void h( int (*array)[length] );

int main() {
    int a[3];
    h(&a);
}


Теперь для вызова шаблонной функции h нужно вывести параметры этого шаблона, за что отвечает вывод типов аргументов (argument type deduction); невероятно умный C++ понимает, что в данном примере length=3.

Ну а так как в C++ есть ссылки и в данном случае они просто удобнее, то можно заменить указатель на ссылку:
template<size_t length>
void hh( int (&array)[length] );

int main() {
    int a[3];
    hh(a);
}
Re: интерпретация T (&array)[size] в шаблонах
От: jazzer Россия Skype: enerjazzer
Дата: 22.12.11 03:40
Оценка: 3 (2)
Здравствуйте, pofig, Вы писали:
P>
P>T (&array)[length]
P>

P> Для чего обязательно амперсанд и скобочки?
Тут шаблон рояли не играет.
амперсанд — это просто объявление ссылки.
скобочки — потому что иначе получится не ссылка на массив, а массив ссылок (который запрещен, но это тут не важно, синтаксически будет именно так). Возникают они из-за того, что в случае массивов и функций тип пишется "вокруг" имени, а не только слева или справа, и непонятно, к чему именно относится звездочка.

С указателем будет то же самое, с точностью до замены амперсанда на звездочку:
int* arr[5];    // массив пяти указателей на инт
int (*parr)[5]; // указатель на массив из пяти интов

int& arr[5];    // массив пяти ссылок на инт (запрещен)
int (&rarr)[5]; // ссылка на массив из пяти интов

int* f();    // функция, возвращающая указатель на инт
int (*pf)(); // указатель на функцию, возвращающую инт

int& f();    // функция, возвращающая ссылку на инт
int (&rf)(); // ссылка на функцию, возвращающую инт

Проблему с "типом вокруг" можно решить тайпдефом — тогда объявления ссылок и указателей приобретут привычный вид:
typedef int ArrType[5]; // тип: массив из пяти интов
typedef int FuncType(); // тип: функция, возвращающая инт

ArrType* parr; // указатель на массив из пяти интов
ArrType& rarr; // ссылка на массив из пяти интов

FuncType* pf;  // указатель на функцию, возвращающую инт
FuncType& rf;  // ссылка на функцию, возвращающую инт
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re: интерпретация T (&array)[size] в шаблонах
От: MasterZiv СССР  
Дата: 22.12.11 08:57
Оценка:
On 12/21/2011 11:04 PM, pofig wrote:

> Объясните плиз как следует понимать конструкцию

>
> T (&array)[length]
>
>
> используемую в шаблонах:
>
> template<typename T,int length>
> void function(T (&array)[length]) {}



T (&array)[length]

--

объявление 1-го параметра функции function с именем параметра "array"
и типом -- ссылка на массив элементов типа "T" размера "length"

> а вот что физически происходит


Объявляется параметр функции с этим типом и именем.

> и почему нужно писать именно так не ясно.


Чтобы передать параметр именно этого типа и потом можно было бы его использовать.

> Для чего обязательно амперсанд и скобочки?


Амперсанд нужен, чтобы объявить параметр как ссылку, чтобы
параметр не передавался по значению, а только ссылка на данные
передавалась.

Скобочки нужны, чтобы расставить приоритет модификаторов в объявлении.
Без скобочек этот параметр имел бы тип
"массив ссылок на элементы типа "T", размера "length" "
вместо
"ссылка на массив элементов типа "T" размера "length""
Мало того, что семантика типа другая, но кроме этого ещё
в С++ массивы ссылок запрещены, так что без скобок не только
это был бы другой тип, но ещё была бы ошибка компиляции.

Кстати, я не знаю, как с массивами ссылок в С++0X
Posted via RSDN NNTP Server 2.1 beta
Re[2]: интерпретация T (&array)[size] в шаблонах
От: Сыроежка  
Дата: 22.12.11 10:03
Оценка:
Здравствуйте, MasterZiv, Вы писали:

MZ>Кстати, я не знаю, как с массивами ссылок в С++0X


Они запрещены. В рабочем проекте стандарта С++ 2011 написано:

"T is called the array element type; this type shall not be a reference type, the (possibly cvqualified)
type void, a function type or an abstract class type."
Меня можно встретить на www.cpp.forum24.ru
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.