2010-05-28 5 views
0

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.

+1

Pourquoi ne pas simplement faire un espace de noms, puis non même mettre les détails privés dans l'en-tête? –

+0

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 .... –

+2

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

Répondre

4

Il se plaint du retour de bien-- set<char>: vous avez oublié d'inclure <set> et utiliser using std::set (ou, de préférence, il suffit de taper sur std::set où vous l'utilisez). Comme pour forcer un argument de modèle à répondre à certaines exigences, le plus simple consiste simplement à écrire votre code de façon à ce qu'il présume que le type répond à ces exigences. Si le type ne répond pas à ces exigences, la compilation échouera.

0

Si vous voulez toujours revenir en jeu, vous pouvez faire votre fonction retourne un ensemble dont le paramètre modèle est un paramètre de modèle de votre fonction:

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); 
Questions connexes