2010-05-28 2 views
0

У меня есть статический класс Utils. Я хочу, чтобы определенные методы были шаблонами, но не весь класс. Как мне это сделать?C++: Шаблоны для статических функций?

Это не удается:

#pragma once 

#include <string> 
using std::string; 

class Utils 
{ 
private: 
    template<class InputIterator, class Predicate> 
    static set<char> findAll_if_rec(InputIterator begin, InputIterator end, Predicate pred, set<char> result); 

public: 
    static void PrintLine(const string& line, int tabLevel = 0); 
    static string getTabs(int tabLevel); 

    template<class InputIterator, class Predicate> 
    static set<char> Utils::findAll_if(InputIterator begin, InputIterator end, Predicate pred); 
}; 

Ошибка:

utils.h(10): error C2143: syntax error : missing ';' before '<' 
utils.h(10): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int 
utils.h(10): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int 
utils.h(10): error C2238: unexpected token(s) preceding ';' 
utils.h(10): error C2988: unrecognizable template declaration/definition 
utils.h(10): error C2059: syntax error : '<' 

Что я делаю неправильно? Каков правильный синтаксис для этого?

Кстати, я хотел бы также запланировать возвращаемое значение. Таким образом, вместо:

template<class InputIterator, class Predicate> 
static set<char> findAll_if_rec(InputIterator begin, InputIterator end, Predicate pred, set<char> result); 

я бы:

template<class return_t, class InputIterator, class Predicate> 
static return_t findAll_if_rec(InputIterator begin, InputIterator end, Predicate pred, set<char> result); 

Как бы указать, что:

1) return_t должен быть набор какой-то

2) InputIterator должен быть итератором

3) InputIterator тип должен работать w с return_t.

Спасибо.

UPDATE: В ответ на людей, которые говорят, что я должен использовать пространство имен intsead в виде Java/C# стиль класса Utils, это еще то, что вы искали:

Utils.h

#pragma once 

#include <string> 
#include <set> 
using std::set; 
using std::string; 

namespace Utils 
{ 
    static void PrintLine(const string& line, int tabLevel = 0); 
    static string getTabs(int tabLevel); 

    template<class result_t, class Predicate> 
    set<result_t> Utils::findAll_if(set<result_t>::iterator begin, set<result_t>::iterator end, Predicate pred); 
}; 

Utils.cpp

#include "Utils.h" 
#include <iostream> 
#include <string> 
using std::string; 
using std::cout; 
using std::endl; 

void Utils::PrintLine(const string& line, int tabLevel) 
{ 
    string tabs = getTabs(tabLevel); 

    cout << tabs << line << endl; 
} 

string Utils::getTabs(int tabLevel) 
{ 
    string tabs; 
    while (tabLevel != 0) 
    { 
     tabs += "\t"; 
     tabLevel--; 
    } 
    return tabs; 
} 

template<class result_t, class Predicate> 
set<result_t> Utils::findAll_if(set<result_t>::iterator begin, set<result_t>::iterator end, Predicate pred) 
{ 
    set<char> result; 
    return findAll_if_rec(begin, end, pred, result); 
} 

template<class result_t, class Predicate> 
set<result_t> findAll_if_rec(set<result_t>::iterator begin, set<result_t>::iterator end, Predicate pred, set<result_t> result) 
{ 
    InputIterator nextResultElem = find_if(begin, end, pred); 
    if (nextResultElem == end) 
    { 
     return result; 
    } 
    result.add(*nextResultElem); 

    return findAll_if_rec(++nextResultElem, end, pred, result); 
} 

У этого есть много ошибок компилятора. Я не думаю, что правильно использую аргумент шаблона result_t.

Update 2 основе замечаний Георга:

Utils.h

#pragma once 

#include <string> 
#include <set> 
using std::set; 
using std::string; 

namespace Utils 
{ 
    void PrintLine(const string& line, int tabLevel = 0); 
    string getTabs(int tabLevel); 

    template<class result_t, class Predicate> 
    set<result_t> Utils::findAll_if(set<result_t>::iterator begin, set<result_t>::iterator end, Predicate pred); 
}; 

namespace detail 
{ 
    template<class result_t, class Predicate> 
    set<result_t> findAll_if_rec(set<result_t>::iterator begin, set<result_t>::iterator end, Predicate pred, set<result_t> result); 
}; 

Utils.cpp

#include "Utils.h" 
#include <iostream> 
#include <string> 
using std::string; 
using std::cout; 
using std::endl; 

void Utils::PrintLine(const string& line, int tabLevel) 
{ 
    string tabs = getTabs(tabLevel); 

    cout << tabs << line << endl; 
} 

string Utils::getTabs(int tabLevel) 
{ 
    string tabs; 
    while (tabLevel != 0) 
    { 
     tabs += "\t"; 
     tabLevel--; 
    } 
    return tabs; 
} 

set<result_t> Utils::findAll_if(set<result_t>::iterator begin, set<result_t>::iterator end, Predicate pred) 
{ 
    set<char> result; 
    return findAll_if_rec(begin, end, pred, result); 
} 

set<result_t> detail::findAll_if_rec(set<result_t>::iterator begin, set<result_t>::iterator end, Predicate pred, set<result_t> result) 
{ 
    InputIterator nextResultElem = find_if(begin, end, pred); 
    if (nextResultElem == end) 
    { 
     return result; 
    } 
    result.add(*nextResultElem); 

    return findAll_if_rec(++nextResultElem, end, pred, result); 
} 

Еще не компилируется. Помогите?

Update 3: Получение ближе ...

Utils.h:

#pragma once 

#include <string> 
#include <set> 
using std::set; 
using std::string; 

namespace Utils 
{ 
    void PrintLine(const string& line, int tabLevel = 0); 
    string getTabs(int tabLevel); 

    template<class result_t, class Predicate> 
    set<result_t> Utils::findAll_if(set<result_t>::iterator begin, set<result_t>::iterator end, Predicate pred) 
    { 
     set<result_t> result; 
     return findAll_if_rec(begin, end, pred, result); 
    } 
} 

namespace detail 
{ 
    template<class result_t, class Predicate> 
    set<result_t> findAll_if_rec(set<result_t>::iterator begin, set<result_t>::iterator end, Predicate pred, set<result_t> result) 
    { 
     set<result_t>::iterator nextResultElem = find_if(begin, end, pred); 
     if (nextResultElem == end) 
     { 
      return result; 
     } 
     result.add(*nextResultElem); 

     return findAll_if_rec(++nextResultElem, end, pred, result); 
    } 
} 

Utils.cpp:

#include "Utils.h" 
#include <iostream> 
#include <string> 
using std::string; 
using std::cout; 
using std::endl; 

void Utils::PrintLine(const string& line, int tabLevel) 
{ 
    string tabs = getTabs(tabLevel); 

    cout << tabs << line << endl; 
} 

string Utils::getTabs(int tabLevel) 
{ 
    string tabs; 
    while (tabLevel != 0) 
    { 
     tabs += "\t"; 
     tabLevel--; 
    } 
    return tabs; 
} 

По-прежнему не компилируется.

+1

Почему бы не просто сделать это пространство имен, а затем не даже поместить личные данные в заголовок? –

+0

Обратите внимание, что компилятор никогда не собирается выводить возвращаемое значение - клиент должен будет явно указать этот аргумент шаблона. Просто, чтобы вы знали .... –

+2

Стилистически, похоже, вы пытаетесь написать Java на C++. Не пытайтесь сделать все классным. Вместо обычного класса утилиты обычный стиль C++ - это просто свободные функции, которые могут быть инкапсулированы в пространство имен. «Публичные» функции объявляются в заголовке и определяются в файле реализации, «частные» функции идут только в анонимном пространстве имен в файле реализации. – Boojum

ответ

4

Он жалуется на возвращение type-- set<char>: вы забыли включить <set> и использовать using std::set (или предпочтительно, просто впечатать std::set где вы его используете).

Что касается форсирования аргумента шаблона для удовлетворения определенных требований, самым простым способом является просто написать код, чтобы он соответствовал этим требованиям. Если тип не отвечает этим требованиям, компиляция завершится неудачей.

0

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

template<class set_t, class InputIterator, class Predicate> 
static std::set<set_t> findAll_if_rec(InputIterator begin, InputIterator end, Predicate pred, std::set<set_t> result); 
Смежные вопросы