J'ai une classe Utils statique. Je veux que certaines méthodes soient modélisées, mais pas toute la classe. Comment puis-je faire cela?C++: Modèles pour les fonctions statiques?
Cela échoue:
#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);
};
Erreur:
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 : '<'
Qu'est-ce que je fais mal? Quelle est la syntaxe correcte pour cela? Incidemment, je voudrais également modéliser la valeur de retour. Ainsi, au lieu de:
template<class InputIterator, class Predicate>
static set<char> findAll_if_rec(InputIterator begin, InputIterator end, Predicate pred, set<char> result);
J'ai:
template<class return_t, class InputIterator, class Predicate>
static return_t findAll_if_rec(InputIterator begin, InputIterator end, Predicate pred, set<char> result);
Comment puis-je préciser que:
1) return_t
doit être un ensemble de quelque sorte
2) InputIterator
doit être un itérateur
3) Le type InputIterator
doit fonctionner avec le type return_t
.
Merci.
MISE À JOUR: En réponse aux gens qui disent que je devrais utiliser un intsead d'espace de noms d'une classe Java/C# style Utils, est-ce plus ce que vous recherchez:
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);
}
Ceci a beaucoup d'erreurs de compilateur. Je ne pense pas que j'utilise l'argument template result_t
correctement.
Update 2 Basé sur les commentaires de Georg:
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);
}
Pas encore la compilation. Aidez-moi?
Mise à jour 3: Se rapprocher ...
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;
}
Toujours ne pas compiler.
Pourquoi ne pas simplement faire un espace de noms, puis non même mettre les détails privés dans l'en-tête? –
Notez qu'un compilateur n'inférera jamais la valeur de retour - un client va devoir spécifier explicitement cet argument template. Juste pour que vous sachiez .... –
Stylistiquement, cela semble que vous essayez d'écrire Java en C++. N'essayez pas de tout faire une classe. Au lieu d'une classe utilitaire comme celle-ci, le style C++ habituel est juste d'avoir des fonctions autonomes, peut-être encapsulées dans un espace de noms. Les fonctions "publiques" sont déclarées dans l'en-tête et définies dans le fichier d'implémentation, les fonctions "privées" ne vont que dans un espace de noms anonyme dans le fichier d'implémentation. – Boojum