Почему вызывается test(char*)?
От: Vain Россия google.ru
Дата: 13.09.06 14:02
Оценка:
namespace A {
  template<int size>
  char* test(char (&str)[size]) {
    return NULL;
  }
  char* test(char *str) {
    return NULL;
  }
}

int main() {
  char arr[] = "";
  A::test(arr);
  return 0;
};


Я так понял неявное приведение вызывается раньше чем инстанцирование шаблона, так?
Это правильно?
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Re: Почему вызывается test(char*)?
От: korzhik Россия  
Дата: 13.09.06 14:06
Оценка:
Здравствуйте, Vain, Вы писали:

V>
V>namespace A {
V>  template<int size>
V>  char* test(char (&str)[size]) {
V>    return NULL;
V>  }
V>  char* test(char *str) {
V>    return NULL;
V>  }
V>}

V>int main() {
V>  char arr[] = "";
V>  A::test(arr);
V>  return 0;
V>};
V>


V>Я так понял неявное приведение вызывается раньше чем инстанцирование шаблона, так?

V>Это правильно?

Да не, просто не шаблонная функция имеет преимущество перед шаблонной
Re[2]: Почему вызывается test(char*)?
От: Vain Россия google.ru
Дата: 13.09.06 14:50
Оценка:
Здравствуйте, korzhik, Вы писали:

V>>Я так понял неявное приведение вызывается раньше чем инстанцирование шаблона, так?

V>>Это правильно?
K>Да не, просто не шаблонная функция имеет преимущество перед шаблонной
Так в данном случае, шаблонная функция, как мне кажется, является более специализированной для массива или нет?
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Re[3]: Почему вызывается test(char*)?
От: ArtDenis Россия  
Дата: 13.09.06 15:52
Оценка:
Здравствуйте, Vain, Вы писали:

V>Так в данном случае, шаблонная функция, как мне кажется, является более специализированной для массива или нет?


Для компилятора сигнатуры функции
  char* test(char str[10]);
  char* test(char *str);

абсолютно одинаковы.

Т.е. твой пример аналогичен коду
char* test(char *&str)
{
    return NULL;
}

char* test(char *str)
{
    return NULL;
}
... << RSDN@Home 1.1.4 stable rev. 510>>
[ 🎯 Дартс-лига Уфы | 🌙 Программа для сложения астрофото ]
Re[4]: Почему вызывается test(char*)?
От: Vain Россия google.ru
Дата: 13.09.06 16:49
Оценка:
Здравствуйте, ArtDenis, Вы писали:

AD>Для компилятора сигнатуры функции

AD>
AD>  char* test(char str[10]);
AD>  char* test(char *str);
AD>

AD>абсолютно одинаковы.
а так?
  char* test(char (&str)[10]);
  char* test(char *str);
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Re[5]: Почему вызывается test(char*)?
От: ArtDenis Россия  
Дата: 13.09.06 17:08
Оценка:
Здравствуйте, Vain, Вы писали:

V>а так?

V>
V>  char* test(char (&str)[10]);
V>  char* test(char *str);
V>


Разные конечно. И кстати, насчёт моего предыдущего поста: я был не прав. Мой пример не аналогичен твоему примеру, т.к. в твоём случае передаётся сслыка на массив char из N элементов, а не ссылка на указатель на char
... << RSDN@Home 1.1.4 stable rev. 510>>
[ 🎯 Дартс-лига Уфы | 🌙 Программа для сложения астрофото ]
Re[6]: Почему вызывается test(char*)?
От: Vain Россия google.ru
Дата: 13.09.06 17:15
Оценка:
Здравствуйте, ArtDenis, Вы писали:

V>>а так?

V>>
V>>  char* test(char (&str)[10]);
V>>  char* test(char *str);
V>>


AD>Разные конечно.

Вот, меня интересует почему это не компилируется.
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Re[7]: Почему вызывается test(char*)?
От: ArtDenis Россия  
Дата: 13.09.06 18:04
Оценка:
Здравствуйте, Vain, Вы писали:
V>Вот, меня интересует почему это не компилируется.

Почему? Компилируется. Правда, если передавать в test массив char из 10-ти элементов, то возникает неоднозначная ситуация при выборе функции, о чём компилятор и сообщает. Во всех других случаях вызывается char* test(char *str)
... << RSDN@Home 1.1.4 stable rev. 510>>
[ 🎯 Дартс-лига Уфы | 🌙 Программа для сложения астрофото ]
Re[8]: Почему вызывается test(char*)?
От: Vain Россия google.ru
Дата: 13.09.06 19:01
Оценка:
Здравствуйте, ArtDenis, Вы писали:

AD>Почему? Компилируется.

Я не про общий случай спрашиваю
AD>Правда, если передавать в test массив char из 10-ти элементов, то возникает неоднозначная ситуация при выборе функции, о чём компилятор и сообщает.
Вот, почему не компилируется. Я не спрашиваю про техническую сторону, она понятна, почему такое вообще не разрешено, каковы причины? Может есть какой пример, который может показать почему должна происходить неоднозначность?
AD>Во всех других случаях вызывается char* test(char *str)
Про эти случаи мне и не интересно
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Re[9]: Почему вызывается test(char*)?
От: ArtDenis Россия  
Дата: 13.09.06 19:42
Оценка:
Здравствуйте, Vain, Вы писали:

V>Вот, почему не компилируется. Я не спрашиваю про техническую сторону, она понятна, почему такое вообще не разрешено, каковы причины? Может есть какой пример, который может показать почему должна происходить неоднозначность?


Неоднозначность происходит в том случае, когда компилятор не знает, вызов какой функции надо подставить, т.к. аргуметы одинаково хорошо подходят для нескольких перегруженных функций:

void test(char (&str)[10]) {}
void test(char *str) {}

char arr[10];

test(arr); // Здесь одинаково хорошо можно подходит char *str и char (&)[10],
           // т.к. массив может передаваться как по указателю, так и по сылке на свой тип



Но в твоём первом примере неоднозначности не происходит, т.к. как тебе уже ответили нешаблонная ф-ция имеет приоритет перед шаблонной.

Чтобы разрулить твою ситуацию можно сделать так:

#include <iostream>

template<int size> char* test(char (&str)[size])
{
    std::cout << "char (&str)[size]" << std::endl;
    return NULL;
}

template<typename T> char* test(T *str);

template<> char* test(char *str)
{
    std::cout << "char *str" << std::endl;
    return NULL;
}

int main()
{
    char arr[] = "data1";
    char *ptr = "data2";
    test(arr);
    test(ptr);
    return 0;
}


В этом случае обе функции будут шаблонные (правда одна из них — специализированная) Это работает на GCC 3.4.2. на остальных — не знаю
... << RSDN@Home 1.1.4 stable rev. 510>>
[ 🎯 Дартс-лига Уфы | 🌙 Программа для сложения астрофото ]
Re[10]: Почему вызывается test(char*)?
От: Vain Россия google.ru
Дата: 13.09.06 21:25
Оценка:
Здравствуйте, ArtDenis, Вы писали:

AD>Неоднозначность происходит в том случае,

Опять, я не спрашиваю почему происходит неоднозначность, я спрашиваю почему она должна происходить, улавливаешь разницу?
AD>Чтобы разрулить твою ситуацию можно сделать так:

AD>
AD>#include <iostream>

AD>template<int size> char* test(char (&str)[size])
AD>{
AD>    std::cout << "char (&str)[size]" << std::endl;
AD>    return NULL;
AD>}

AD>template<typename T> char* test(T *str);

AD>template<> char* test(char *str)
AD>{
AD>    std::cout << "char *str" << std::endl;
AD>    return NULL;
AD>}

AD>int main()
AD>{
AD>    char arr[] = "data1";
AD>    char *ptr = "data2";
AD>    test(arr);
AD>    test(ptr);
AD>    return 0;
AD>}
AD>

Если это работает на GCC, то тем более, как мне кажется, должно также и это работать:
char* test(char (&)[10]) {
  return NULL;
}
char* test(char*) {
  return NULL;
}
void main() {
  char arr[10] = "";
  test(arr); //вызов char* test(char (&)[10])
}


AD>В этом случае обе функции будут шаблонные (правда одна из них — специализированная)

под vs80 не работает

PS:
Есть здесь знатоки стандарта, что по этому поводу он говорит?
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Re: Почему вызывается test(char*)?
От: Bell Россия  
Дата: 14.09.06 07:09
Оценка: +1
Здравствуйте, Vain, Вы писали:

V>
V>namespace A {
V>  template<int size>
V>  char* test(char (&str)[size]) {
V>    return NULL;
V>  }
V>  char* test(char *str) {
V>    return NULL;
V>  }
V>}

V>int main() {
V>  char arr[] = "";
V>  A::test(arr);
V>  return 0;
V>};
V>


V>Я так понял неявное приведение вызывается раньше чем инстанцирование шаблона, так?


На первый взгляд кажется, что шаблон, принимающий массив по ссылке, имеет преимущество, т.к. тут очевидный Exact Match,а для второй функции не все так очевидно.
Смотрим 4.2/2
A string literal (2.13.4) that is not a wide string literal can be converted 
to an rvalue of type pointer to char;
...
For the purpose of ranking in overload resolution (13.3.3.1.1), 
this conversion is considered an array-to-pointer conversion 
followed by a qualification conversion (4.4).


Смотрим 13.3.3.1.1/3, таблицу 9. Там написано, что Array-to-pointer conversion и qualification conversion суть Exact Match, и
и поэтому получается, что вариант test(char *str) — тоже Exact Match, а значит имеет преимущество перед шаблоном.

Для иллюстрации можно привести такой пример:
namespace A {
  char* test(char (&str)[1]) {
    return 0;
  }
  char* test(char *str) {
    return 0;
  }
}

int main() {
  char arr[] = "";
  int  arr[sizeof(A::test(arr))];
  return 0;
};


В данном случае имеет место быть неоднозначность.

Обсуждение этой проблемы можно посмотреть также здесь
Автор: _Winnie
Дата: 14.03.06
Любите книгу — источник знаний (с) М.Горький
Re[2]: Почему вызывается test(char*)?
От: Vain Россия google.ru
Дата: 14.09.06 11:48
Оценка:
Здравствуйте, Bell, Вы писали:

B>Смотрим 13.3.3.1.1/3, таблицу 9. Там написано, что Array-to-pointer conversion и qualification conversion суть Exact Match, и

Вот мне кажется что Array-to-pointer должен быть неявным преобразованием, вам не кажется?
B>и поэтому получается, что вариант test(char *str) — тоже Exact Match, а значит имеет преимущество перед шаблоном.
Перед шаблоном — да, а перед обычной функций по логике вещей должна быть нормальная перегрузка, а её нет, это то и недочёт.

B>Для иллюстрации можно привести такой пример:

B>
B>namespace A {
B>  char* test(char (&str)[1]) {
B>    return 0;
B>  }
B>  char* test(char *str) {
B>    return 0;
B>  }
B>}

B>int main() {
B>  char arr[] = "";
B>  int  arr[sizeof(A::test(arr))];
B>  return 0;
B>};
B>

так sizeof(char*) там в любом случае будет
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Re[3]: Почему вызывается test(char*)?
От: Bell Россия  
Дата: 14.09.06 12:40
Оценка:
Здравствуйте, Vain, Вы писали:

V>так sizeof(char*) там в любом случае будет

Остальось от пердыдущих экспериментов
Любите книгу — источник знаний (с) М.Горький
Re[11]: Почему вызывается test(char*)?
От: Станислав Артемкин  
Дата: 15.09.06 08:31
Оценка:
V>Опять, я не спрашиваю почему происходит неоднозначность, я спрашиваю почему она должна происходить, улавливаешь разницу?

Так как в противном случае нарушалась бы семантика вызова в зависимости от контекста.

Имеем
void test(const char(&)[5])   // (1)
{
   // do something
}
void test(const char*)        // (2)
{
   // do something different
}


Допустим, что обе функции не равнозначны с точки зрения перегрузки для массива из 5 элементов, т.е. первая предпочтительнее т.к. не требует array-to-pointer conversion.

test("test"); // "test" - это array of 5 const char, вызывается (1).

const char* name = "test";
test(name);   // name - это pointer to const char, вызывается (2).


Получаем опасную неоднозначность вызова.
Стас
Re[12]: Почему вызывается test(char*)?
От: Vain Россия google.ru
Дата: 15.09.06 13:49
Оценка:
Здравствуйте, Станислав Артемкин, Вы писали:

СА>
СА>test("test"); // "test" - это array of 5 const char, вызывается (1).

СА>const char* name = "test";
СА>test(name);   // name - это pointer to const char, вызывается (2).
СА>


СА>Получаем опасную неоднозначность вызова.

почему опасную?
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.