Здравствуйте, SVV, Вы писали:
Ложки нет (С) Из наставлений для Нео по шаблонному программированию.
Никаких специализаций шаблонов в С++ не существует. Шаблонов тоже не существует. Т.е. названия такие есть, но они суть умозрительные категории — не обращай на них внимание. ты должен помнить, что
а) шаблон это что-то вроде макроса, только строго типизированный
б) сам шаблон не порождает кода
в) там, где ты используешь шаблон — происходит инстанцирование класса
г) инстанции класса в реальности существуют. Шаблоны — нет! Т.е. std::vector<int> в точке инстанцирования точно существует. Но это некий отдельный класс, который не имеет отношения к исходному шаблону. Связь между шаблоном и инстанциеей односторонняя!!!
д) Частичная специализация шаблона для класса — это отдельный шаблон. В нём может быть всё по другому, правил нет!!!
наподобие перегруженных функций. test (int) и test (int, void*) — это две разные функции с одинаковым названием.
e) Если частичная специализация шаблона для класса задаёт один-единственный класс, а не семейство классов, то он связан с материнским шаблоном так же, как и инстанция шаблона связана с ним — никак!!! Компилер считает их разными шаблонами с одним именем, и при встрече инстанции пытается дедуктивно вывести, какое из твоих определений подставить
ещё раз — специализация шаблона может быть другой по смыслу. вплоть до смешного.
//класс, который моет окна
template<typename WindowType> Wash {
public:
void Start(WindowType & arg) {StartWash(arg);}
private:
void StartWash(WindowType & arg);
}
//класс, который запускает ракеты
template<typename Rocket1, typename Rocket2> Wash {
public:
void start(Rocket1 & rocket) {LaunchRocket(rocket);}
void start(Rocket2 & rocket) {LaunchRocket(rocket);}
private:
void LaunchRocket(Rocket1 & rocket);
void LaunchRocket(Rocket2 & rocket);
}
class Window {};
class RoundWindow : public Window {};
class TriangleWindow : public Window {};
void int main(int argc, char *argv[])
{
RoundWindow rw;
TriangleWindow tw;
Wash<RoundWindow> wash1;
Wash<TriangleWindow> wash2;
Wash<RoundWindow, TriangleWindow> wash3;
wash1->start(rw); //помыли круглое окно
wash2->start(tw); //помыли треугольное окно
wash3->start(tw); //запустили ракету в космос
}
Здравствуйте, _NN_, Вы писали:
_NN>Здравствуйте, SVV, Вы писали:
SVV>>да, так. только это не прокатывает. vs2012 update5
_NN>Убрать нужно скобки:
_NN>Test<char>::Test
_NN>_NN>#include <iostream>
_NN>using namespace std;
_NN>template<class T>
_NN>class Test
_NN>{
_NN>public:
_NN> template<class T2>
_NN> Test(const T2* sz)
_NN> {
_NN> printf ("common version\n");
_NN> }
_NN>protected:
_NN>};
_NN>template<>
_NN>template<>
_NN>Test<char>::Test(const wchar_t* sz)
_NN>{
_NN> printf ("a.w. str: %S\n", sz);
_NN>}
_NN>template<>
_NN>template<>
_NN>Test<wchar_t>::Test(const char* sz)
_NN>{
_NN> printf ("w.a str: %s\n", sz);
_NN>}
_NN>int main() {
_NN> Test<char> a("A");
_NN> Test<char> b(L"B");
_NN> Test<wchar_t> c("C");
_NN> Test<wchar_t> d(L"D");
_NN> return 0;
_NN>}
_NN>
_NN>_NN>Microsoft (R) C/C++ Optimizing Compiler Version 17.00.50727.1 for x64
_NN>Copyright (C) Microsoft Corporation. All rights reserved.
_NN>a.cpp
_NN>Microsoft (R) Incremental Linker Version 11.00.50727.1
_NN>Copyright (C) Microsoft Corporation. All rights reserved.
_NN>/out:a.exe
_NN>a.obj
специализация вида
template<>
template<>//2 раза
Test<wchar_t>::Test(const char* sz)
{
printf ("w.a str: %s\n", sz);
}
должна размещаться в cpp файле (иначе проблемы при линковке с множественным определением символа), а специализация вида
template<>//1 раз
Test::Init(const char* sz)
{
printf ("w.a str: %s\n", sz);
}
должна быть в h файле (иначе при линковке символ не виден везде где нужен).
Таким образом, если в специализации Init (т.е. в h файле) я использую конструктор (специализация которого в cpp файле далее и "сейчас" не доступна), то возникает ошибка компиляции (в cpp файле компилятор не принимает специализацию утверждая что там уже лишнее). Вероятно это потому что класс в h файле компилятор создал как мог.
Можно ли как-то перенести специализацию (констректора например) в определение класса (в h файле) или сделать что-то типа "forward declaration"?
P.S. в классе Test<char>::Init понадобилось использовать класс Test<wchar>::Test... Обойти можно, но получается не очень красиво
SVV>специализация вида
SVV>SVV>template<>
SVV>template<>//2 раза
SVV>inline Test<wchar_t>::Test(const char* sz)
SVV>{
SVV> printf ("w.a str: %s\n", sz);
SVV>}
SVV>
SVV>должна размещаться в cpp файле (иначе проблемы при линковке с множественным определением символа), а специализация вида
Или добавить
inline в заголовочном файле
Здравствуйте, SVV, Вы писали:
SVV> а специализация вида
SVV>SVV>template<>//1 раз
SVV>Test::Init(const char* sz)
SVV>{
SVV> printf ("w.a str: %s\n", sz);
SVV>}
SVV>
SVV>должна быть в h файле (иначе при линковке символ не виден везде где нужен).
Тут что-то не так...
SVV>Можно ли как-то перенести специализацию (констректора например) в определение класса (в h файле) или сделать что-то типа "forward declaration"?
Это :
//.h
// ...
template<>
template<>
Test<char>::Test(const wchar_t* sz);
template<>
template<>
Test<wchar_t>::Test(const char* sz);
— в .h файл.
А определения в .cpp:
//.cpp
template<>
template<>
Test<char>::Test(const wchar_t* sz)
{
printf ("a.w. str: %S\n", sz);
}
template<>
template<>
Test<wchar_t>::Test(const char* sz)
{
printf ("w.a str: %s\n", sz);
}
Спс. Сразу попробовал в определение класса в h файл — не прокатило. Видимо нельзя там template<>template<> прописывать, а вот если после определения класса в h файле, то прокатило!
SVV>есть такой класс:
SVV>SVV>template<class T>
SVV>class Test
SVV>{
SVV>public:
SVV> template<class T2>
SVV> Test(const T2* sz)
SVV> {
SVV> printf ("common version\n");
SVV> }
SVV> template<>
SVV> Test(const char* sz)
SVV> {
SVV> printf ("T.a. str: %s\n", sz);
SVV> }
SVV> template<>
SVV> Test(const wchar* sz)
SVV> {
SVV> printf ("T.w. str: %S\n", sz);
SVV> }
SVV>protected:
SVV>};
[ccode]
template<class T>
class Test
{
public:
...
template<class NotT>
Test(NotT *sz);
...
Если Т=char, то конструктор должен быть только для NotT=wchar (не для char)
Если Т=wchar то конструктор должен быть только для NotT=char (не для wchar)
если
template<>template<>Test<char>::Test(char) просто не реализовывать, то ошибка появляется только на этапе линковки. А хотелось бы чтобы она была на этапе компиляции. Можно так сделать?
Я бы и рад обойтись вообще без шаблонов тут, но не знаю как.
Вот если бы можно было что-то типа
#if sizeof(T)==1
или
#if typeof(T)==char
...
Здравствуйте, SVV, Вы писали:
SVV>Я бы и рад обойтись вообще без шаблонов тут, но не знаю как.
SVV>Вот если бы можно было что-то типа
SVV>#if sizeof(T)==1
SVV>или
SVV>#if typeof(T)==char
SVV>...
| | может так? |
| | template<typename T> struct AArgSelector;
template<> struct AArgSelector<int> { typedef void* Type; };
template<> struct AArgSelector<void*> { typedef int Type; };
template<typename T>
class A {
public:
A( typename AArgSelector<T>::Type ) {}
};
int main() {
A<void *> a0( 5 );
//A<int> a1(5);
A<int> a2(&a0);
return 0;
}
|
| | |
http://ideone.com/RLaNbl
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском