Специализация шаблонной функции
От: ss_greh  
Дата: 28.05.04 04:34
Оценка:
Имеется шаблонная функция, принимающая один аргумент по ссылке на константу.
И два ее специализированных варианта для const char* и char*.

template<class T>
void test(const T& t)
    {
    }

template<>
void test(char const* const& t)
    {
    }

template<>
void test(char* const& t)
    {
    }


Собственно проверка

int main()
    {
    const char* test1 = "test";
    char* test2 = "test";

    test(test1); // N1
    test(test2); // N2
    test("test");// N3
    }


При вызове test под номером один, как и следовало ожидать, вызывается специализированная под const char* функция.
При вызове test под номером два — специализированная под char* функция.

Догадайтесь, какую из трех функция вызывает test N3?
Ответ: Общую шаблонную функцию.

Не могу понять почему. На сколько я знаю в C++ строковый литералы имеют тип const char*.
Или я ошибаюсь?

Да, забыл сказать — компилятор VS7.1.
Re: Специализация шаблонной функции
От: kvas Россия  
Дата: 28.05.04 05:07
Оценка:
Здравствуйте, ss_greh, Вы писали:

здесь
Автор: Павел Кузнецов
Дата: 08.12.03
Re: Специализация шаблонной функции
От: Tolyan www.kbsoft-group.com
Дата: 28.05.04 05:12
Оценка:
Здравствуйте, ss_greh, Вы писали:


_>При вызове test под номером один, как и следовало ожидать, вызывается специализированная под const char* функция.

_>При вызове test под номером два — специализированная под char* функция.

_>Догадайтесь, какую из трех функция вызывает test N3?

_>Ответ: Общую шаблонную функцию.

_>Не могу понять почему. На сколько я знаю в C++ строковый литералы имеют тип const char*.

_>Или я ошибаюсь?

Точно const char* и в общей шаблонной функции у тебя const T&, т.е. const char*&
Re[2]: Специализация шаблонной функции
От: ss_greh  
Дата: 28.05.04 05:19
Оценка:
Здравствуйте, Tolyan, Вы писали:

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



_>>При вызове test под номером один, как и следовало ожидать, вызывается специализированная под const char* функция.

_>>При вызове test под номером два — специализированная под char* функция.

_>>Догадайтесь, какую из трех функция вызывает test N3?

_>>Ответ: Общую шаблонную функцию.

_>>Не могу понять почему. На сколько я знаю в C++ строковый литералы имеют тип const char*.

_>>Или я ошибаюсь?

T>Точно const char* и в общей шаблонной функции у тебя const T&, т.е. const char*&


И?

template<>
void test(const char*&)
    {
    }


не является специализацией

template<class T>
void test(const T& t)
    {
    }


Что ты хотел этим сказать?
Re: Специализация шаблонной функции
От: Demay  
Дата: 28.05.04 05:30
Оценка: 4 (2)
Здравствуйте, ss_greh, Вы писали:

_>Имеется шаблонная функция, принимающая один аргумент по ссылке на константу.

_>И два ее специализированных варианта для const char* и char*.

_>
_>template<class T>
_>void test(const T& t)
_>    {
_>    }

_>template<>
_>void test(char const* const& t)
_>    {
_>    }

_>template<>
_>void test(char* const& t)
_>    {
_>    }
_>


_>Собственно проверка


_>
_>int main()
_>    {
_>    const char* test1 = "test";
_>    char* test2 = "test";

_>    test(test1); // N1
_>    test(test2); // N2
_>    test("test");// N3
_>    }
_>


_>При вызове test под номером один, как и следовало ожидать, вызывается специализированная под const char* функция.

_>При вызове test под номером два — специализированная под char* функция.

_>Догадайтесь, какую из трех функция вызывает test N3?

_>Ответ: Общую шаблонную функцию.

_>Не могу понять почему. На сколько я знаю в C++ строковый литералы имеют тип const char*.

_>Или я ошибаюсь?

Вы ошибаетесь.
В процессе вывода аргументов преобразование из массива в указатель происходит только в том случае, если параметр имеет не ссылочный тип. У вас в test("test") аргумент, представляющий собой строковый литерал, который передается шаблонам функций, параметры которых объявлены как параметры ссылочного типа. Т.е. в test("test") параметр передается как ссылка на массив из 5-ти символов. Если вы желаете получить явную специализацию шаблонной функции необходимо воспользоваться перегрузкой для массива, например:
template< typename T, int N >
void test( T const (&t)[N] ) {
}

Или отказаться от использования ссылок, в пользу передачи по значению.
Re: Специализация шаблонной функции
От: Vamp Россия  
Дата: 28.05.04 05:38
Оценка: 3 (2) +1
_>Не могу понять почему. На сколько я знаю в C++ строковый литералы имеют тип const char*.
Нет. const char [].
Но существует правило "распада" указателя, не применяющееся в этом случае.
Так что все правильно.
Да здравствует мыло душистое и веревка пушистая.
Re[2]: Специализация шаблонной функции
От: ss_greh  
Дата: 28.05.04 05:52
Оценка:
Здравствуйте, Vamp, Вы писали:

_>>Не могу понять почему. На сколько я знаю в C++ строковый литералы имеют тип const char*.

V>Нет. const char [].
Хорошо. Меня ввела в заблуждение книга Николая Джосаттиса "С++ стандартная библиотека".
В ней черным по белому, в главе посвещенной строкам, написано:

...
Учтите, что тип строковых литералов (например, "hello") был заменен на const char*. Тем не менее
для обеспечение совместимости поддерживается неявное (хотя и нежелательное) преобразование к char*.
...


Буду теперь думать, прежде чем верить печатному слову.

V>Но существует правило "распада" указателя, не применяющееся в этом случае.

V>Так что все правильно.

Спасибо за разъяснение.
Re[3]: Специализация шаблонной функции
От: Vamp Россия  
Дата: 28.05.04 05:57
Оценка: 1 (1)
_>Буду теперь думать, прежде чем верить печатному слову.

Слово слову рознь. Истинное слово — в стандарте . В данном случае, 2.13.4, пункт 1:

...An ordinary string literal has the type "array of n const char"...


_>Спасибо за разъяснение.

Всегда рад.
Да здравствует мыло душистое и веревка пушистая.
Re[2]: Специализация шаблонной функции
От: kvas Россия  
Дата: 28.05.04 06:01
Оценка:
V>Так что все правильно.


Т.е. в данном случае для достижения нужного поведения нужно написать что-то вроде
template<int N>
void test(const char (&)[N])
    {
    }


P.S. Кстати, пару минут назад видел чье-то сообщение с таким-же кодом. Потом его удалили. Почему?
Re[3]: Специализация шаблонной функции
От: ss_greh  
Дата: 28.05.04 06:07
Оценка:
Здравствуйте, kvas, Вы писали:

V>>Так что все правильно.



K>Т.е. в данном случае для достижения нужного поведения нужно написать что-то вроде

K>
K>template<int N>
K>void test(const char (&)[N])
K>    {
K>    }
K>

ок. а будет ли эта функция специализацией

template<class T>
void test(const T& t)
    {
    }


??
Re[4]: Специализация шаблонной функции
От: Demay  
Дата: 28.05.04 06:16
Оценка:
Здравствуйте, ss_greh, Вы писали:

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


V>>>Так что все правильно.



K>>Т.е. в данном случае для достижения нужного поведения нужно написать что-то вроде

K>>
K>>template<int N>
K>>void test(const char (&)[N])
K>>    {
K>>    }
K>>

_>ок. а будет ли эта функция специализацией

_>
_>template<class T>
_>void test(const T& t)
_>    {
_>    }
_>


_>??


Будет не специализацией, а перегрузкой.
Re[5]: Специализация шаблонной функции
От: ss_greh  
Дата: 28.05.04 06:22
Оценка:
Здравствуйте, Demay, Вы писали:

K>>>Т.е. в данном случае для достижения нужного поведения нужно написать что-то вроде

K>>>
K>>>template<int N>
K>>>void test(const char (&)[N])
K>>>    {
K>>>    }
K>>>

_>>ок. а будет ли эта функция специализацией

_>>
_>>template<class T>
_>>void test(const T& t)
_>>    {
_>>    }
_>>


_>>??


D>Будет не специализацией, а перегрузкой.

поэтому и спрашивал

Тогда уж проще воспользоваться перегрузкой:
void test(const char*)
    {
    }
Re[3]: Специализация шаблонной функции
От: Demay  
Дата: 28.05.04 07:13
Оценка:
Здравствуйте, ss_greh, Вы писали:

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


_>>>Не могу понять почему. На сколько я знаю в C++ строковый литералы имеют тип const char*.

V>>Нет. const char [].
_>Хорошо. Меня ввела в заблуждение книга Николая Джосаттиса "С++ стандартная библиотека".
_>В ней черным по белому, в главе посвещенной строкам, написано:
_>

_>...
_>Учтите, что тип строковых литералов (например, "hello") был заменен на const char*. Тем не менее
_>для обеспечение совместимости поддерживается неявное (хотя и нежелательное) преобразование к char*.
_>...


_>Буду теперь думать, прежде чем верить печатному слову.


Джосьютис не сказал ничего неверного.
Его слова о типе строковых литералов в главе 11 относятся к конструкторам string, которые получают строковые литералы по значению как const char*. У вас первичный шаблон функции test, (primary template) и его специализации получают ссылку. Поэтому! проявляется проблема несоответствия между массивом символов и указателем на символы.
Если обьявить первичный шаблон функции test получающим указатель, затем, специализировать его типом const char*, вы получите вызов специализации const char* в строке N3 вашего первого поста, которую вы и ожидали в первом посте.

template<class T>
void test(const T* t) {
}

template<> // в строке N3 вызов будет сюда
void test( const char* t ) {
}
Re[4]: Специализация шаблонной функции
От: ss_greh  
Дата: 28.05.04 07:45
Оценка:
Здравствуйте, Demay, Вы писали:

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


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


_>>>>Не могу понять почему. На сколько я знаю в C++ строковый литералы имеют тип const char*.

V>>>Нет. const char [].
_>>Хорошо. Меня ввела в заблуждение книга Николая Джосаттиса "С++ стандартная библиотека".
_>>В ней черным по белому, в главе посвещенной строкам, написано:
_>>

_>>...
_>>Учтите, что тип строковых литералов (например, "hello") был заменен на const char*. Тем не менее
_>>для обеспечение совместимости поддерживается неявное (хотя и нежелательное) преобразование к char*.
_>>...


_>>Буду теперь думать, прежде чем верить печатному слову.


D>Джосьютис не сказал ничего неверного.

D>Его слова о типе строковых литералов в главе 11 относятся к конструкторам string, которые получают строковые литералы
Цитата, приведенная мною выше, взята из краткого предисловия к 11 главе. В нем ни слова не говорится о конструкторах класса basic_string<>, зато дается определение тому, что можно понимать под строкой.
Именно в этом контексте Nicolai Josuttis пишет про тип строковых литералов.
Re[3]: Специализация шаблонной функции
От: sergey_shandar США http://getboost.codeplex.com/
Дата: 28.05.04 08:01
Оценка:
Здравствуйте, kvas, Вы писали:

K>P.S. Кстати, пару минут назад видел чье-то сообщение с таким-же кодом. Потом его удалили. Почему?

Мое. Только когда его запостил, то увидел сообшения от Vamp и Demay, и понял что мое становиться просто бессмысленным, и сам удалил его (что бы не повторяться). А по поводу того являеться ли она перегрузкой или специализацией, не знаю. Слишком мутно все в языке C++
getboost.codeplex.com
citylizard.codeplex.com
Re[4]: Специализация шаблонной функции
От: Lorenzo_LAMAS  
Дата: 28.05.04 08:10
Оценка: :)
Различие между перегрузкой и специализациями отнюдь не мутно и очень даже четко.
Of course, the code must be complete enough to compile and link.
Re: Специализация шаблонной функции
От: MaximE Великобритания  
Дата: 29.05.04 10:35
Оценка: 1 (1)
ss_greh wrote:

> Догадайтесь, какую из трех функция вызывает test N3?

> Ответ: Общую шаблонную функцию.
>
> Не могу понять почему. На сколько я знаю в C++ строковый литералы имеют тип const char*.
> Или я ошибаюсь?

Раз уж ты под VS7.1, то добавил бы строчечку:

template<class T>
void test(const T& t)
{
    std::cout << __FUNCSIG__ << '\n';
}


Получил бы вывод:

void __cdecl test<const char[5]>(const char (&)[5])


И вопросы бы сразу отпали

--
Maxim Yegorushkin
Posted via RSDN NNTP Server 1.9 alpha
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.