2012-02-08 3 views
3

Учитывая этот пример, который включает в себя несколько перегруженных перегрузки:C++ оператор преобразования и разрешение

#include <iostream> 

class T 
{ 
    public: 
     operator const wchar_t *(void) const 
     { 
     std::cout << "Conversion" << std::endl; 
     return L"Testing"; 
     } 
}; 

template <class Elem> 
class A 
{ 
}; 

template <class T> 
void operator <<(A<T> &, const T *) 
{ 
    std::cout << "1" << std::endl; 
} 

template <class T> 
void operator <<(A<T> &, const void *) 
{ 
    std::cout << "2" << std::endl; 
} 

int main(void) 
{ 
    A<wchar_t> test; 
    T   source; 

    test << L"1"; 
    test << static_cast<const wchar_t *>(source); 
    test << source; 
} 


и его выход:

1 
Conversion 
1 
Conversion 
2 


Мой вопрос - почему void operator <<(A<T> &, const void *) который вызывается для заявления test << source;? Может ли кто-нибудь указать конкретную часть стандарта, который охватывает этот случай?

ответ

4

Поскольку вывод аргумента шаблона не принимает во внимание неявные преобразования. Результатом является то, что, когда Вы писали:

test << source; 

, компилятор не может найти подходящий T для первой функции шаблона; он пытается найти T, так что T const* имеет то же самое , что и ваш T, что невозможно. Вывод аргумента невозможен, и не добавляется экземпляр шаблона в набор перегрузки. Начиная с нет аргумента шаблона во втором параметре второго шаблона функции , вычет аргументов для отказа отсутствует, а итоговый экземпляр становится единственным членом набора перегрузки, и так будет выбрано.

0

Используется неявное преобразование T в wchar_t. Любой тип конвертируется в void*, поэтому компилятор называет эту версию operator<<. Оператор T* никогда не был кандидатом, потому что не было никакого способа получить T* неявно от T. вы хотели сделать это оператором T&<<?

+0

Нет, этот пример был структурирован после того, как работает iostreams. (Почти). В частности, я использовал класс, у которого был оператор преобразования, для const wchar_t *, и неясно, почему вызывался перегруженный оператор '<< (.., const void *)' для широкоформатная версия потока. – DOS

0

Неявный вывод аргументов шаблона не будет учитывать пользовательские неявные преобразования. Поскольку такой вызов template <class T> void operator <<(A<T> &, const T *) выводит T как wchar_t из первого аргумента, но второй аргумент T вместо const wchar_t*. Поэтому компилятор не сможет сопоставить этот оператор.

Для вопроса template <class T> void operator <<(A<T> &, const void *) дело выглядит иначе: T будет выведено как wchar_t из аргумента первой функции. Второй аргумент может быть неявно преобразован в const wchar_t* с помощью определенного пользователем преобразования, которое затем может быть неявно передано в const void* путем преобразования в преобразование. Поэтому эта функция вызывается с этими аргументами и используется, так как другая не может быть выведена.

Смежные вопросы