C ++: шаблоны для статических функций? - PullRequest
0 голосов
/ 28 мая 2010

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

Это не удалось:

#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 должен работать с типом return_t.

Спасибо.

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

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.

Обновление 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);
}

Все еще не компилируется. Помощь

Обновление 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;
}

Все еще не компилируется.

Ответы [ 2 ]

4 голосов
/ 28 мая 2010

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

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

0 голосов
/ 28 мая 2010

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

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);
...