Форум программистов, компьютерный форум CyberForum.ru

C++

Войти
Регистрация
Восстановить пароль
 
Tulosba
:)
Эксперт С++
4387 / 3230 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
#1

Выбор шаблонного варианта для аргумента-массива - C++

10.10.2014, 21:40. Просмотров 589. Ответов 15
Метки нет (Все метки)

По стопам оффтопа в теме решил создать свою. Для ускорения прояснения ситуации, так сказать.

Имеем код:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
 
template <class T>
void func( T& t ) {
    std::cout << "&" << sizeof(t) << std::endl;
}
template <class T>
void func( T* t) {
    std::cout << "*" << sizeof(t) << std::endl;
}
int main() {
    char a[10] = "bla-bla";
    func(a); 
    return 0;
}
http://ideone.com/KDBqyW
Почему вызывается версия с указателем, а не с ссылкой!?

Любопытно, что если в шаблоны добавить const, то будет вызываться версия со ссылкой.
А если сам массив сделать константным, то снова версия с указателем.
Лучшие ответы (1)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
10.10.2014, 21:40     Выбор шаблонного варианта для аргумента-массива
Посмотрите здесь:

Перегрузка operator<< для шаблонного класса C++
Перегрузка << , >> для шаблонного класса C++
пространство имен для шаблонного класса C++
C++ Builder C++ Builder 2006. Выбор варианта для выполнения
не удается релизовать свою функцию sort для шаблонного массива C++
C++ Выбор одного варианта из двух
C++ Как для шаблонного класса определить действие для частного случая
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
zss
Модератор
Эксперт С++
6184 / 5787 / 1874
Регистрация: 18.12.2011
Сообщений: 14,782
Завершенные тесты: 1
10.10.2014, 22:14     Выбор шаблонного варианта для аргумента-массива #2
По логике должно быть так
C++
1
2
func(a); // вызов с указателем: a- адрес переменной
func(*a); // вызов со ссылкой: *a - разыменованная переменная
MrGluck
Ворчун
Эксперт CЭксперт С++
6404 / 3602 / 448
Регистрация: 29.11.2010
Сообщений: 9,528
10.10.2014, 22:56     Выбор шаблонного варианта для аргумента-массива #3
zss, вопрос в том, почему компилятор иногда передаёт адрес всего массива, а иногда адрес первого элемента в массиве.
Jewbacabra
Эксперт PHP
2056 / 1720 / 631
Регистрация: 24.04.2014
Сообщений: 4,900
10.10.2014, 23:03     Выбор шаблонного варианта для аргумента-массива #4
Цитата Сообщение от Tulosba Посмотреть сообщение
если в шаблоны добавить const, то будет вызываться версия со ссылкой
Tulosba, компилятор MSVS 13 - всегда вызывается версия с указателем
IGPIGP
Комп_Оратор)
6363 / 3010 / 297
Регистрация: 04.12.2011
Сообщений: 8,101
Записей в блоге: 3
11.10.2014, 01:22     Выбор шаблонного варианта для аргумента-массива #5
Цитата Сообщение от Jewbacabra Посмотреть сообщение
Tulosba, компилятор MSVS 13 - всегда вызывается версия с указателем
И в 2008 тоже. Но так же и должно быть? Имя массива T преобразуется к указателю на 1-й элемент везде, где ожидается указатель на T. Туда где ожидается ссылка на тип можно передать переменную типа, но не указатель же?
DrOffset
6840 / 4051 / 924
Регистрация: 30.01.2014
Сообщений: 6,855
11.10.2014, 03:05     Выбор шаблонного варианта для аргумента-массива #6
Сообщение было отмечено автором темы, экспертом или модератором как ответ
Цитата Сообщение от Tulosba Посмотреть сообщение
Почему вызывается версия с указателем, а не с ссылкой!?
Если по-простому и на пальцах, то потому что T недостаточно квалифицирован для подстановки. В то время как перегрузка с указателем обеспечивает array-to-pointer conversion, которая одного ранга (Exact Match) с отсутствием какой-либо конверсии, а значит более предпочтительна (см. таблицу в 13.3.3.1.1).
Когда ты добавляешь const к варианту с указателем, то получаешь дополнительно qualification conversion. Перегрузка, требующая конверсии, теряет приоритет перед вариантом со ссылкой.
Чтобы получить нужное тебе поведение, надо в варианте со ссылкой квалифицировать T достаточным образом (тип массива в С++ представляет собой комбинацию типа и размерности):
C++
1
2
3
4
5
6
7
8
9
template <class T>
void func( T * t) {
    std::cout << "*" << sizeof(t) << std::endl;
}
 
template <class T>
void func( T (& t)[10]) {
    std::cout << "&" << sizeof(t) << std::endl;
}
Итого получаем ошибку неоднозначности, теперь перегрузки равны в глазах компилятора. Исправить это можно только вынеся размерность в аргумент шаблона, чтобы вариант начал рассматриваться исходя из подстановки, а не на общих основаниях.
C++
1
2
3
4
template <class T, size_t N>
void func( T (& t)[N]) {
    std::cout << "&" << sizeof(t) << std::endl;
}
Цитата Сообщение от IGPIGP Посмотреть сообщение
Туда где ожидается ссылка на тип можно передать переменную типа, но не указатель же?
Дело в том, что изначально массив не указатель и требует array-to-pointer conversion при передаче, так что вариант с T & может подойти, T разрешится в ссылку на массив. Но массив сложный тип и квалификации T недостаточно для выбора в нашем случае. В то время как преобразование к указателю имеет высокий приоритет, наравне с отсутствием преобразования.

Добавлено через 22 минуты
Как-то я главное не подчеркнул:
В данном случае, с использованием шаблонов помимо правил собственно перегрузки еще вступает в силу параграф 14.8.2. Т.е. сначала определяется, скажем так, степень выводимости шаблона (это не термин, если что), а потом уже правила перегрузки, поэтому-то и влияет так сильно уровень квалификации T. Компилятору не нужно выводить размерность массива, если мы ее указали явно. А в варианте с обычной ссылкой нужно вывести в T еще и размерность массива, поэтому наиболее простым вариантом остается array-to-pointer конвертация, которая, как я уже сказал, идентична по рангу отсутствию конвертации.
Tulosba
:)
Эксперт С++
4387 / 3230 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
11.10.2014, 13:35  [ТС]     Выбор шаблонного варианта для аргумента-массива #7
Цитата Сообщение от DrOffset Посмотреть сообщение
Перегрузка, требующая конверсии, теряет приоритет перед вариантом со ссылкой.
Не очень понял, почему преобразование к ссылке (не важно, константной или нет) приоритетнее преобразования к константному указателю.
Цитата Сообщение от DrOffset Посмотреть сообщение
Исправить это можно только вынеся размерность в аргумент шаблона,
И убрав при этом версию с указателем вовсе?
IGPIGP
Комп_Оратор)
6363 / 3010 / 297
Регистрация: 04.12.2011
Сообщений: 8,101
Записей в блоге: 3
11.10.2014, 18:16     Выбор шаблонного варианта для аргумента-массива #8
Цитата Сообщение от DrOffset Посмотреть сообщение
Дело в том, что изначально массив не указатель и требует array-to-pointer conversion при передаче, так что вариант с T & может подойти
Я прошу прощения, - шаблоны и разрешения перегрузки с неявными преобразованиями, это сложно для меня, но я не понимаю Почему имя массива может подойти там где объявлена ссылка на тип и ожидается то что приводится к T?
Имя массива не приводится.
Я поэкспериментировал, кое-что подсмотрел в:
http://rsdn.ru/forum/cpp/1957817.all
хотя подозревал, что-то подобное. Тут два несовместимых фрагмента, поэтому закомментировав код с шаблоном принимающим ссылку на массив ( вот тут действительно имя проходит ) придётся раскомментировать варианты со ссылкой на тип и указатель.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <iostream>
using namespace std;
//это разрэмить
/*
template <typename T>
void foo(T& t){
cout << "&" << sizeof(t)<<endl;
}
template <typename T>
void foo(T* t){
cout << "*" << sizeof(t)<<endl;
}*/
 
//это зарэмить
template <typename T, size_t N>
void foo(T (&t)[N]) {
cout << "T (&t)[N]" << sizeof(t)<<endl;
}
 
int main()
{
    int a[] = {1,2,3};
    int (&c)[3] = a;//ссылка на массив
    int d = a[0]; //тип
//это разремить
/*
foo(a);//неявно a to &a[0] то есть к T*
foo(*a);//a to a[0] то есть к T и можно передать в T&
foo(c);//int (&c)[3] to &a[0] ! то есть снова к T*, ссылка на массив и ссылка на тип разные звери и преобразование к ссылке int& не будeт и тут
*/
//это зарэмить
foo(a);//массив по ссылке
cout <<  endl;
    system("pause");
    return 0;
}
Возможно я и близко не понял о чём речь.
DrOffset
6840 / 4051 / 924
Регистрация: 30.01.2014
Сообщений: 6,855
11.10.2014, 23:15     Выбор шаблонного варианта для аргумента-массива #9
IGPIGP, у тебя в самом начале рассуждений ошибка, которая и завела тебя в тупик.
Вот здесь:
Цитата Сообщение от IGPIGP Посмотреть сообщение
то есть снова к T*, ссылка на массив и ссылка на тип разные звери и преобразование к ссылке int& не будeт и тут
никто не утверждал, что будет преобразование к ссылке на тип. Я писал:
Цитата Сообщение от DrOffset Посмотреть сообщение
T разрешится в ссылку на массив
Т.е. при использовании варианта
C++
1
2
template <typename T>
void foo(T & t)
с аргументом a, где а объявлен как int a[100], то T будет int[100], итого получим ссылку на массив, при подстановке T = int[100] аргумент будет выглядеть как int (&)[100].

Цитата Сообщение от Tulosba Посмотреть сообщение
Не очень понял, почему преобразование к ссылке (не важно, константной или нет) приоритетнее преобразования к константному указателю.
Скопирую ответ из ЛС:
Цитата Сообщение от DrOffset Посмотреть сообщение
Преобразование к ссылке рассматривается как отсутсвие (identity) преобразования (13.3.3.1.4) в нашем случае.
Преобразование к указателю одного ранга с отсутствием преобразования (демонстрация неоднозначности в моем посте)
А вот константность добавляет Qualification conversion, которая не смотря опять же на одинаковый ранг, разрешается исходя из фактической cv-квалификации аргумента (см. 13.3.3.2/3). Если есть перегрузка, где не требуется преобразование неконст->конст то будет выбрана именно она.
Цитата Сообщение от Tulosba Посмотреть сообщение
И убрав при этом версию с указателем вовсе?
Да, придется убрать. Впрочем, можно не обращать внимания на ту часть моего ответа, где я предлагал способ лечения этого, т.к. я слегка торопился и скомкал эту часть, да и к теме это напрямую не относится - все и так знают как это лечить.

Добавлено через 6 минут
Цитата Сообщение от IGPIGP Посмотреть сообщение
Почему имя массива может подойти там где объявлена ссылка на тип и ожидается то что приводится к T?
Она подойдет если нет других более подходящих вариантов. Об этом и была речь. В варианте Tulosba более подходящей является перегрузка с указателем. Добавив const к ней мы сделали более подходящим вариант со ссылкой. Про детали я уже выше написал.

Добавлено через 12 минут
Вообще вся эта кухня на самом деле довольно сложна.
Но можно использовать небольшие эмпирические правила:
1) Всегда применяется наиболее специализированный шаблон.
2) Перегрузка разрешается всегда в пользу наименьшего количества преобразований (или их отсутствия).
IGPIGP
Комп_Оратор)
6363 / 3010 / 297
Регистрация: 04.12.2011
Сообщений: 8,101
Записей в блоге: 3
12.10.2014, 00:11     Выбор шаблонного варианта для аргумента-массива #10
Цитата Сообщение от DrOffset Посмотреть сообщение
IGPIGP, у тебя в самом начале рассуждений ошибка, которая и завела тебя в тупик.
Возможно. Давай поговорим:
Цитата Сообщение от DrOffset Посмотреть сообщение
никто не утверждал, что будет преобразование к ссылке на тип. Я писал:
Цитата Сообщение от DrOffset Посмотреть сообщение
T разрешится в ссылку на массив
Я понимаю, что объявление в коде и в формальных параметрах имеет совершенно разный смысл:
C++
1
2
3
4
int a=123;
int &ref_a=a;//объявлен псевдоним для a без создания переменной
//а тут:
void foo( int &a);//грубо говоря, функция ожидает имя переменной с типом: всё что неявно преобразуемо к int
Но синтаксически они: int &var_name, то есть идентичны. Я не большой знаток и нигде не видел, чтобы писалось, что такая идентичность, - закон, но думал, что так и есть. Разубеди меня.
Ссылка на массив это же не ссылка на тип (элементов массива). То что массив это не тип"недотип", а именно массив (элементов)типа, предлагаю, тут не затрагивать. Достаточно того, что ни внутренне ни внешне эти ссылки не имеют ничего общего:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//переменная типа int
int b=123;
 
//ссылка на int 
int &a = b;//псевдоним b
 
//функция объявляет формальный параметр - ссылка int
void foo(int &c);//сюда можно передать и a и b
 
 
//массив тип/ов/а int
int a[3] = {1, 2, 3};
 
//ссылка на имя массива a
int (&ref_arr_a)[3] = a;
 
//синтаксически от объявления void foo(int &c); тоже отличается и тоже сходно с прямым объявлением переменной- ссылки:   
void foo(int (&ref_arr)[3]); //функция ожидает массив int из 3 элементов по ссылке
В чём же логическая ошибка. И у кого?
зы: робко предполагаю, что компилятор который допускает преобразование массива к ссылке T& не должен бы этого делать.
DrOffset
6840 / 4051 / 924
Регистрация: 30.01.2014
Сообщений: 6,855
12.10.2014, 02:28     Выбор шаблонного варианта для аргумента-массива #11
Цитата Сообщение от IGPIGP Посмотреть сообщение
Но синтаксически они: int &var_name, то есть идентичны. Я не большой знаток и нигде не видел, чтобы писалось, что такая идентичность, - закон, но думал, что так и есть. Разубеди меня
Не буду разубеждать, потому что эти выкладки не относятся к теме вопроса

Цитата Сообщение от IGPIGP Посмотреть сообщение
робко предполагаю, что компилятор который допускает преобразование массива к ссылке T& не должен бы этого делать.
Ты не читаешь что я тебе пишу.
Это меня печалит.

Давай еще раз:
C++
1
2
3
4
5
    typedef int T [100];
 
    int a[100];
 
    T & ar = a;
Аналогично с шаблоном и изначальным примером. Вместо T подставляется int[100] (реальный тип аргумента), добавляем ссылку - получаем ссылку на массив.

Добавлено через 11 минут
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int a[100];
 
template <typename T>
void foo(T & a);
 
// Вызываем
foo(a);
 
// Выводится T = int[100]
 
template <typename T = int[100]> //T выведен
void foo(T & a); //<-- к T добавляется ссылка
 
//Итого, тип аргумента:
void foo(int (&a)[100]);
В общем я не знаю как еще объяснять

Добавлено через 13 минут
Цитата Сообщение от IGPIGP Посмотреть сообщение
Ссылка на массив это же не ссылка на тип (элементов массива).
Ссылка на массив - это именно ссылка на тип. Где тип - это тип массива, включающий в себя тип элементов и размерность, т.е. тип составной.
Сбивает с толку чудная запись типа посередине? Ну так это синтаксическая фишка такая в С\С++. В С\С++ объявление можно представить в виде prefix Name suffix, где префикс и суффикс — какие-то строки, вместе образующие правильное выражение. Соответственно, производные типы получаются добавлением операторов (*, &, const, volatile, (), []) к префиксу/суффиксу.
По поводу "недо...". Функции и массивы в С++ непервоклассные объекты (non first class objects), отсюда их свойства: функции нельзя создавать в рантайме. Объект с типом "массив" в рантайме тоже создать нельзя (выражение new возвращает указатель). Функции не копируются, вместо этого приводятся к указателю на функцию, с массивами аналогично.
IGPIGP
Комп_Оратор)
6363 / 3010 / 297
Регистрация: 04.12.2011
Сообщений: 8,101
Записей в блоге: 3
12.10.2014, 03:46     Выбор шаблонного варианта для аргумента-массива #12
Цитата Сообщение от DrOffset Посмотреть сообщение
В общем я не знаю как еще объяснять
Я понимаю, что ты говоришь, - массив это тип и передать его можно по ссылке T& где T - абстрактный тип. Мой компилятор против. А у меня логика, которая тоже против. Ссылка на массив имеет отдельный синтаксис и typedef ничего не объясняет. Он то подставит именно правильное объявление и по форме (синтаксически) и по содержанию, - с размером массива то есть. Это же компилтайм трюк. Вот когда ты сказал:
Цитата Сообщение от DrOffset Посмотреть сообщение
тип массива в С++ представляет собой комбинацию типа и размерности
Цитата Сообщение от DrOffset Посмотреть сообщение
Но массив сложный тип и квалификации T недостаточно для выбора в нашем случае.
Мне и захотелось сказать: "И..." То есть правильно же. У массива есть синтаксис определения ссылки и там вся необходимая информация, как и должно быть. Поэтому к ссылке на тип и не приводится. Но возник спор. Не стану упорствовать.

Добавлено через 59 минут
Цитата Сообщение от IGPIGP Посмотреть сообщение
Не стану упорствовать.
Эт я погорячился. Как и со всем остальным. Признаю что неправ. Только-что сделал вот что: оставил определение шаблона:
C++
1
2
3
4
template <typename T>
void foo(T& t){
cout << "&" << sizeof(t)/sizeof(t[0])<<endl;
}
в одиночестве. И компилятор стал передавать имя массива по ссылке на него! И это значит, что ты прав и когда они в паре с шаблоном для T* то последний побеждает потому, что его проще вывести...
Тогда непонятно, почему нет неоднозначности? Такое ощущение, что компилятор не видит шаблон с T& когда есть вариант с T*. А ведь оба вызываются одинаково.
Удивление усиливает то, что если оставить такие два:
C++
1
2
3
4
5
6
7
8
template <typename T, size_t N>
void foo(T (&t)[N]) {
cout << "T (&t)[N] with N= " << sizeof(t)/sizeof(T)<<endl;
}
template <typename T>
void foo(T* t){
cout << "*" << sizeof(t)<<endl;
}
то компилируется только если закоментировать вызов foo(a); , а иначе неоднозначный вызов! Почему же Т* и T& уживаются, а T* и T (&t)[N] нет? Я потому и решил сначала, что T& не в тему и тогда есть логика, как мне казалось. Оказывается если "дожать" и оставить T& в одиночестве, - Ok! Пусть T* "легчевыводимее" T&, почему они не дерутся, в то время когда одновременно определённые T* и T (&t)[N] не переносят вызов по имени массива? Не уж-то ссылка T (&t)[N] борется с T* за имя массива уже преобразованное к указателю? Кем и зачем? Не понимаю.
Так или иначе, а я оказался неправ. Приношу извинения.
DrOffset
6840 / 4051 / 924
Регистрация: 30.01.2014
Сообщений: 6,855
12.10.2014, 10:54     Выбор шаблонного варианта для аргумента-массива #13
Цитата Сообщение от IGPIGP Посмотреть сообщение
почему они не дерутся, в то время когда одновременно определённые T* и T (&t)[N] не переносят вызов по имени массива?
В принципе ответ на этот вопрос есть в моих предыдущих постах.
Вариант T & слишком общий, вместо T здесь может быть что угодно, не только массив.
Вариант с T (&t)[N] - такой же как как вариант с T * они одно значно квалифицируют сущность аргумента. Логика на пальцах:
Заменив T на тип (простая замена T = int), мы можем сразу сказать какой у нас аргумент.
В варианте с T & недостаточно заменить T = int, нужно еще вывести N. Это сложнее и компилятор отбрасывает эту перегрузку.
Чтобы понять этот механизм посмотри вот сюда. Представь, что эти шаги выполняются при построении AST компилятором. Чем больше нужно прыгать (там в примере 7 раз), тем сложнее вывод. Таким образом компиляторо способен (и делает) проводить разрешение перегрузки только между наиболее специализированными шабонами, наибольшая специализация определяется из сложности вывода типа, чем больше информации указано в помощь выводу, тем проще. Поэтому, кстати, нужно брать ссылку в скобочки в определении ссылки на массив, для того, чтобы парсер смотрел ее сразу за декларатором аргумента.

Добавлено через 8 минут
Цитата Сообщение от IGPIGP Посмотреть сообщение
Ссылка на массив имеет отдельный синтаксис и typedef ничего не объясняет.
Синтаксис определения типа в С++ один:
Цитата Сообщение от DrOffset Посмотреть сообщение
prefix Name suffix, где префикс и суффикс — какие-то строки, вместе образующие правильное выражение.
IGPIGP
Комп_Оратор)
6363 / 3010 / 297
Регистрация: 04.12.2011
Сообщений: 8,101
Записей в блоге: 3
12.10.2014, 13:06     Выбор шаблонного варианта для аргумента-массива #14
Цитата Сообщение от DrOffset Посмотреть сообщение
Вариант T & слишком общий, вместо T здесь может быть что угодно, не только массив.
Тогда он должен бы драться с любым аргументом (без модификаторов), но спасает отсутствие явного указания размера. То есть лень ему вот и не дерётся.
Цитата Сообщение от DrOffset Посмотреть сообщение
Вариант с T (&t)[N] - такой же как как вариант с T * они одно значно квалифицируют сущность аргумента.
Сущность это как-то религиозно что ли. Указатель и ссылка это же не одно и то же, даже если внутренне ссылка на массив это указатель + размер... Почему дерутся? Усиление однозначности порождает неоднозначность несмотря на различие типов? Наверное дело в вызове. Получив имя трудно понять просят ли передать по ссылке или по указателю. Я думаю в первом случае это противоречие тоже есть, но трудоемкость (компилятору лень) это скрывает. Вообще, создаётся впечатление, что семантика ссылки на массив конфликтует с семантикой ссылки как таковой применительно к шаблонам. Вдобавок неявное преобразование имени к ссылке или указателю не определено приоритетно (иначе не понимаю в чем неоднозначность) и чтобы разные компиляторы не делали как придётся, одновременное сосуществование признано несъедобным. Вообще набор правил вывода наверное если не самое сложное, что есть, то во всяком случае достаточно сложная штука. Буду читать. Спасибо, DrOffset.
DrOffset
6840 / 4051 / 924
Регистрация: 30.01.2014
Сообщений: 6,855
12.10.2014, 15:04     Выбор шаблонного варианта для аргумента-массива #15
Цитата Сообщение от IGPIGP Посмотреть сообщение
Почему дерутся? Усиление однозначности порождает неоднозначность несмотря на различие типов? Наверное дело в вызове. Получив имя трудно понять просят ли передать по ссылке или по указателю.
Посмотри таблицу в п. 13.3.3.1.1 привязка к ссылке на массив и array-to-pointer conversion одного ранга, потому и дерутся.

Добавлено через 3 минуты
Цитата Сообщение от IGPIGP Посмотреть сообщение
То есть лень ему вот и не дерётся.
Ну множно и так сказать. Он рассматривает при перегрузке только равноквалифицированные варианты шаблонов, менее квалифицированные теряют приоритет.

Добавлено через 1 минуту
Цитата Сообщение от IGPIGP Посмотреть сообщение
Сущность это как-то религиозно что ли. Указатель и ссылка это же не одно и то же
Они равнозначны с точки зрения ранга преобразования при разрешении перегрузки. см. таблицу.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
12.10.2014, 15:48     Выбор шаблонного варианта для аргумента-массива
Еще ссылки по теме:

Как перегрузить операторы для шаблонного класса? C++
Чтение из файла и заполнение шаблонного массива C++
Несколько типов данных для шаблонного класса C++
Перегрузить приведение типов для шаблонного класса C++
итератор для шаблонного класса C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
IGPIGP
Комп_Оратор)
6363 / 3010 / 297
Регистрация: 04.12.2011
Сообщений: 8,101
Записей в блоге: 3
12.10.2014, 15:48     Выбор шаблонного варианта для аргумента-массива #16
Цитата Сообщение от DrOffset Посмотреть сообщение
Посмотри таблицу в п. 13.3.3.1.1 привязка к ссылке на массив и array-to-pointer conversion одного ранга, потому и дерутся.
Вот теперь как-то прояснилось. Таким образом неоднозначность порождается равным приоритетом (преобразования к разным типам(!)). То есть когда передаётся ссылка на массив как на тип: T&, компилятор имеет проблему с определением размера и выбирает указатель. Так ему легче. Допустим. А когда передаётся ссылка на массив: T (&)[N] транслятор сразу видит размер и ему одинаково просто выбрать и T* и T (&)[N]... То есть с его точки зрения T& и T (&)[N] это одно и тоже, но... не одно и тоже. Для T& нужно искать размер, который в коде может быть не задан явно и т.п. То есть разрешение определяется не различием типов, а различием сложности трансляции?!
Я могу задавать глупые вопросы, так как в шаблонах не шибко. То есть с моей точки зрения контейнеры (а массив - встроенный контейнер), векторы, списки, словом все типы размер которых определяется определением (масло-масляное)), принципиально отличаются от фиксированных типов вроде простых встроенных типов и фиксированных пользовательских. Тут чувствую ещё много открытий. Что же, тем лучше. Ещё раз спасибо, DrOffset. Было интересно и с удовольствием.
ps много то есть, - мой грех, но разнообразить уже не успею.
Yandex
Объявления
12.10.2014, 15:48     Выбор шаблонного варианта для аргумента-массива
Ответ Создать тему
Опции темы

Текущее время: 08:39. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru