Отсутствие ортогональности в шаблонах между классом и функцией - PullRequest
2 голосов
/ 30 сентября 2010
// InternalTemplate.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

template<class T>
struct LeftSide
{
 static void insert(T*& newLink, T*& parent)
 {
  parent->getLeft() = newLink;
  newLink->parent = newLink;
 }
};

template<class T>
struct Link
{
 T* parent_;
 T* left_;
 T* right_;
 T*& getParent()const
 {
  return parent_;
 }
 template<class Side>
 void plugIn(Link<T>*& newLink);


};

template<class T>
template<class Side>
void Link<T>::plugIn(Link<T>*& newLink)//<<-----why can't I type  
//void Link<T>::plugIn<Side>(Link<T>*& newLink)<---<Side> next to plugIn


{
 Side::insert(newLink,this);
}

int _tmain(int argc, _TCHAR* argv[])
{
 return 0;
}

Мне кажется странным, что я должен указать параметр для класса, но не могу указать параметр для функции. Есть ли причина почему?

Ответы [ 3 ]

2 голосов
/ 06 февраля 2011

Шаблоны функций и шаблоны классов дополняют друг друга (я называю их ортогональными, но вы можете не соглашаться), и в шаблонном метапрограммировании они фактически служат ортогональным целям.

Шаблоны классов позволяют вам шаблонсовпадение в аргументе шаблона, т.е.они обеспечивают частичную специализацию .

Шаблоны функций, напротив, не допускают частичную специализацию, но они позволяют вычитать аргументы шаблона , что означает, что вы этого не делаетеЯ должен написать аргументы шаблона явно (за исключением дополнительных аргументов, как в вашем примере).

Это, я думаю, объясняет различия в синтаксисе, поскольку они различаются в том, чего они могут достичь.Более того, шаблоны функций могут иметь перегрузки, шаблоны классов не могут.

Способ объединить обе концепции -

1) иметь шаблоны классов помощников со статическими функциями, не являющимися шаблонами, если вы хотите частичную специализацию для функциишаблоны:

template <typename T>
struct doSomethingWithPointersHelper
{
    static void act(T x) { ... }
};

template <typename T>
struct doSomethingWithPointersHelper<T*>
{
    static void act(T* x) { ... }
};

// This acts as if we had a partial specialization
// for pointer types
template <typename T>
doSomethingWithPointers(T x)
{ return doSomethingWithPointersHelper<T>::act(x); }

Существуют и другие способы достижения этого в отдельных случаях, но этот подход всегда работает.

2) Наличие вспомогательных шаблонных функций, если вы хотите использовать аргументную дедукциюпри построении сложных классов:

template <typename T, typename U>
struct MyComplexClass
{ ... };

template <typename T, typename U>
MyComplexClass<T, U> makeComplex(T t, U u)
{ return MyComplexClass<T, U>(t, u); }

в стандартной библиотеке вы найдете make_pair, bind1st или mem_fun, которые используют эту технику.

1 голос
/ 30 сентября 2010

$14/2 -

Объявление шаблона может появляться только как объявление области имен или области действия класса. В объявлении шаблона функции последним компонентом идентификатора объявления должен быть имя-шаблона или идентификатор-оператора-оператора (т. Е. Не идентификатор-шаблона). [Примечание: в объявлении шаблона класса, еслиимя класса - это простой-идентификатор шаблона, объявление объявляет частичную специализацию шаблона класса (14.5.5).- конец примечания] "

Стандарт явно запрещает такой синтаксис. См. Это для получения дополнительной информации о идентификатор шаблона / имя шаблона

0 голосов
/ 30 сентября 2010

Вам нужно специализироваться на структуре Link, чтобы определить ее функцию-член шаблона.

template<>
template<class Side>
void Link<int>::plugIn(Link<int>*& newLink)
{
 Side::insert(newLink,this);
}

Должен быть честным, это заставляет мой мозг немного взорваться.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...