У меня есть статический класс 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;
}
По-прежнему не компилируется.
Почему бы не просто сделать это пространство имен, а затем не даже поместить личные данные в заголовок? –
Обратите внимание, что компилятор никогда не собирается выводить возвращаемое значение - клиент должен будет явно указать этот аргумент шаблона. Просто, чтобы вы знали .... –
Стилистически, похоже, вы пытаетесь написать Java на C++. Не пытайтесь сделать все классным. Вместо обычного класса утилиты обычный стиль C++ - это просто свободные функции, которые могут быть инкапсулированы в пространство имен. «Публичные» функции объявляются в заголовке и определяются в файле реализации, «частные» функции идут только в анонимном пространстве имен в файле реализации. – Boojum