Re: Специализация шаблонов по 2 параметрам
От: Molchalnik  
Дата: 25.02.16 11:34
Оценка:
Здравствуйте, 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); //запустили ракету в космос

}
Re[4]: Специализация шаблонов по 2 параметрам
От: SVV Беларусь  
Дата: 21.03.16 13:41
Оценка:
Здравствуйте, _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... Обойти можно, но получается не очень красиво
Re[5]: Специализация шаблонов по 2 параметрам
От: _NN_  
Дата: 21.03.16 14:13
Оценка: 2 (1)
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 в заголовочном файле
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[5]: Специализация шаблонов по 2 параметрам
От: B0FEE664  
Дата: 21.03.16 15:07
Оценка: 6 (1) +1
Здравствуйте, 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);
}
И каждый день — без права на ошибку...
Re[6]: Специализация шаблонов по 2 параметрам
От: SVV Беларусь  
Дата: 21.03.16 16:04
Оценка:
Спс. Сразу попробовал в определение класса в h файл — не прокатило. Видимо нельзя там template<>template<> прописывать, а вот если после определения класса в h файле, то прокатило!
Re: Как запретить некоторые конструкторы?
От: SVV Беларусь  
Дата: 26.03.16 19:53
Оценка:
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
...
Re[2]: Как запретить некоторые конструкторы?
От: Erop Россия  
Дата: 27.03.16 07:59
Оценка: 6 (1)
Здравствуйте, 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
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.