Перегрузка шаблонной и не шаблонной функций
От: kvser  
Дата: 25.04.11 07:01
Оценка:
#include <iterator>

namespace myspace
{
struct mystruct{};
void distance(mystruct a, mystruct b)
{
}
}

int main()
{
using namespace myspace;
using namespace std;

mystruct a,b;
distance(a,b); //1
}

http://codepad.org/eYGf0wTp
Почему в 1 компилятор отдает предпочтение шаблонной функции?
Re: Перегрузка шаблонной и не шаблонной функций
От: MasterZiv СССР  
Дата: 25.04.11 07:53
Оценка:
On 25.04.2011 11:01, kvser wrote:

> Почему в 1 компилятор отдает предпочтение шаблонной функции?


По стандарту. Если есть подходящая для вызова нешаблонная
функция, шаблонная генерироваться не будет.
Posted via RSDN NNTP Server 2.1 beta
Re[2]: Перегрузка шаблонной и не шаблонной функций
От: kvser  
Дата: 25.04.11 08:02
Оценка:
Здравствуйте, MasterZiv, Вы писали:

MZ>On 25.04.2011 11:01, kvser wrote:


>> Почему в 1 компилятор отдает предпочтение шаблонной функции?


MZ>По стандарту. Если есть подходящая для вызова нешаблонная

MZ>функция, шаблонная генерироваться не будет.

почему тогда в этом примере пытается сгенерироваться шаблонная функция std::distance
есть же подходящая нешаблонная
Re: Перегрузка шаблонной и не шаблонной функций
От: Ops Россия  
Дата: 25.04.11 08:21
Оценка:
Здравствуйте, kvser, Вы писали:

K>Почему в 1 компилятор отдает предпочтение шаблонной функции?


Не нашел шаблонной функции. Специально набирал "template" в поиске. Что я делаю не так?
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.
Re[2]: Перегрузка шаблонной и не шаблонной функций
От: Alexey F  
Дата: 25.04.11 08:41
Оценка:
Здравствуйте, Ops, Вы писали:

Ops>Не нашел шаблонной функции. Специально набирал "template" в поиске. Что я делаю не так?

Эмм... А как же std::distance из iterator? o_O
Re: Перегрузка шаблонной и не шаблонной функций
От: andrey.desman  
Дата: 25.04.11 08:49
Оценка:
Здравствуйте, kvser, Вы писали:

K>Почему в 1 компилятор отдает предпочтение шаблонной функции?


http://groups.google.com/group/comp.lang.c++.moderated/browse_thread/thread/3c449572456c8592/9e07411a9ba5f615?#9e07411a9ba5f615
Re[2]: Перегрузка шаблонной и не шаблонной функций
От: andrey.desman  
Дата: 25.04.11 09:01
Оценка: 8 (2)
Здравствуйте, andrey.desman, Вы писали:

AD>Здравствуйте, kvser, Вы писали:


K>>Почему в 1 компилятор отдает предпочтение шаблонной функции?


AD>http://groups.google.com/group/comp.lang.c++.moderated/browse_thread/thread/3c449572456c8592/9e07411a9ba5f615?#9e07411a9ba5f615


А вот почему здесь не работает SFINAE (проблема происходит еще до выбора перегрузки, а в момент инстанцировании std::distance):

Here is what happens (in a reduced example):

#include <iostream>

template<class T> struct trait {
     typedef typename T::type type;

};

namespace A {

     struct X {
         typedef int type;
     };

     template<class T> typename trait<T>::type f(T) {
         return 0;
     }

}

int f(A::X) {
     return 1;

}

int main(void) {
     std::cout << f(A::X()) << '\n';
     return 0;

}

The overload selected is the global one, and the output of the program is 1.
However, if you comment out the typedef in X, you get the same kind of error.
In other words, in this (and the original) example overload resolution is doing
the right thing. The problem occurs before overload resolution--during argument
deduction on the template function found through ADL prior to it being added to
the candidate set. SFINAE doesn't apply here, because trait<T> does have a
nested ::type, it is just that X (with the typedef commented) does not. ::type
is being used outside of the declaration (where SFINAE applies) in traits<T>
(where SFINAE doesn't apply). I.e. SFINAE applies here...
template<class T> typename trait<T>::type f(T);
                                    ^^^^^^
but does not apply here...

template<class T> struct trait {
     typedef typename T::type type;
                       ^^^^^^

};

Now, the instantiation of trait<T> is a full instantiation that includes the
instantiation of its member typedefs. In the original example, the failure
isn't because vector doesn't have ::difference_type (it does); the failure is
because vector doesn't have ::iterator_category.

Note that if trait was defined differently, such as

template<class T> struct trait : T { };

Then the access would be in the function declaration, causing SFINAE to apply,
and silently removing the function as a candidate.

If the compiler was required to apply SFINAE to arbitrary depths of template
instantiations, then the compiler would have to be able to roll back all those
instantiations when a type substitution failed. Vendors have been complaining
about this being extremely difficult for some time now, and it is the primary
reason (AFAICT) that SFINAE does not apply to expressions. Personally, I think
that vendors should bite the bullet, because C++ would be a better language if
it did this. It leads to surprising (and very indirect) errors because it does
not. Unfortunately, that is the way it is right now.

Re[2]: Перегрузка шаблонной и не шаблонной функций
От: kvser  
Дата: 25.04.11 09:12
Оценка:
Здравствуйте, Ops, Вы писали:

Ops>Здравствуйте, kvser, Вы писали:


K>>Почему в 1 компилятор отдает предпочтение шаблонной функции?


Ops>Не нашел шаблонной функции. Специально набирал "template" в поиске. Что я делаю не так?


а там шаблонная std::distance приходит еще
Re: Перегрузка шаблонной и не шаблонной функций
От: Masterkent  
Дата: 25.04.11 09:20
Оценка: 4 (1)
kvser:

K>
K>#include <iterator>

K>namespace myspace
K>{
K>struct mystruct{};
K>void distance(mystruct a, mystruct b)
K>{
K>}
K>}

K>int main()
K>{
K>using namespace myspace;
K>using namespace std;

K>mystruct a,b;
K>distance(a,b); //1
K>}
K>

K>http://codepad.org/eYGf0wTp
K>Почему в 1 компилятор отдает предпочтение шаблонной функции?

Он не отдаёт ей предпочтение. Когда шаблон функции является кандидатом, производится попытка инстанцировать прототип функции на основе этого шаблона путём подстановки выведенных и явно указанных аргументов шаблона на место его параметров. Если подстановка аргументов шаблона приводит к попытке создания в immediate контексте некорректной конструкции, входящей в перечень, описанный в C++03 — 14.8.2/2 (в случае C++0x рассматриваются любые некорректные конструкции в immediate контексте), и не приводит к ошибкам в non-immediate контекстах, то прототип функции не добавляется в конечный набор функций-кадидатов. Ситуация, когда ошибки одновременно возникают как в immediate, так и в non-immediate контекстах, правилами не оговариваются (и реализации ведут себя по-разному). Если ошибки возникают только в non-immediate контекстах, то программа безоговорочно некорректна (при этом не имеет никакого значения, есть ли среди кандидатов функция, которая имела бы преимущество перед любой корректной специализацией какого-либо шаблона функции). Ошибка, возникающая в процессе инстанцирования специализации шаблона класса (в данном случае это std::iterator_traits), относится к non-immediate контексту.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.