требуется синтаксическая помощь для шаблонной статической функции-члена - PullRequest
1 голос
/ 23 марта 2010

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

// Code sketch only - detail fleshed out below...  
class ObjectListDiagnoser  
{  
public:  
    static void GenerateDiagnostics( /* help required here! */ );  
};  

...

// Elsewhere in the system...  
ObjectListDiagnoser::GenerateDiagnostics( /* help required here! */ );  

То, что я хотел бы сделать (в некоторых местах моего приложения), это как минимум следующее:

std::vector<MyObject *> objGroup1;  
std::list<MyObject *> objGroup2;

ObjectListDiagnoser::GenerateDiagnostics( objGroup1.begin(), objGroup1.end() );  
ObjectListDiagnoser::GenerateDiagnostics( objGroup2.begin(), objGroup2.end() );  
ObjectListDiagnoser::GenerateDiagnostics( objGroup1.rbegin(), objGroup1.rend() );  

Я пытался шаблонировать свою функцию двумя способами, но безуспешно:

class ObjectListDiagnoser  
{  
public:  
    // 1 - nope.  
    template <class ObjIter>
    static void GenerateDiagnostics( ObjIter first, ObjIter last );  
    // 2. - nope.  
    template <class Container, class ObjIter>
    static void GenerateDiagnostics( Container<MyObject *>::ObjIter first,  
                                     Container<MyObject *>::ObjIter last );  
};  

Может ли кто-нибудь предоставить правильный синтаксис для этого? Тип контейнера будет меняться, и направление итерации будет меняться, но всегда для одного и того же типа объекта.


Резюме обсуждения в комментариях ниже - случай 1 верен ... но приводит к широко неразборчивой ошибке компоновщика, если определение функции шаблона отсутствует в заголовке. Определения шаблонных функций просто должны идти в заголовке - точка, которую легко забыть. Вставьте его в шапку, и все хорошо - компилирует, ссылки ... и, надеюсь, даже работает.

Ответы [ 2 ]

1 голос
/ 23 марта 2010

Вы должны использовать опцию 1. Как и в случае функций из <algorithm>, типы контейнеров не входят в аргументы шаблона.

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

template <class ObjIter>
static void ObjectListDiagnoser::GenerateDiagnostics
 ( ObjIter first, ObjIter last ) {
   …
}

РЕДАКТИРОВАТЬ: как и для всех шаблонов, это определение должно быть в файле заголовка.Использование шаблона вне исходного файла, в котором он определен, широко не поддерживается.

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

// implementation in source file

template <class ObjIter>
static void ObjectListDiagnoser::GenerateDiagnostics
 ( ObjIter first, ObjIter last ) {
   …
}

template void ObjectListDiagnoser::GenerateDiagnostics
  < std::list<Object>::iterator >
 ( std::list<Object>::iterator first, std::list<Object>::iterator last );

template void ObjectListDiagnoser::GenerateDiagnostics
  < std::vector<Object>::iterator >
 ( std::vector<Object>::iterator first, std::vector<Object>::iterator last );

// now you can only use vector<Object>::iterator or list<Object>::iterator
// as arguments.
0 голосов
/ 23 марта 2010

Я согласен с @sth, что с 1 нет проблем. Фактически, так объявляются алгоритмы STL - find

Если 1 работает, нет необходимости в 2. Любым способом его объявление должно быть

template <class Container>
static void GenerateDiagnostics( typename Container<MyObject *>::iterator first, 
       typename Container<MyObject *>::iterator last );  

Обратите внимание - это всего лишь пример, который будет работать с iterator контейнера и может не работать с reverse_iterator или const_iterator

...