Наличие класса или функции в качестве параметра шаблона - PullRequest
3 голосов
/ 19 декабря 2010

Я не знал, что искать, поэтому постараюсь объяснить как можно лучше.В STL std::set определяется как

template <class Key, class Compare, class Allocator> class set;

С http://cplusplus.com:

Сравнение : Класс сравнения: класс, который принимает два аргумента одного типав качестве элементов контейнера и возвращает bool.Выражение comp (a, b), где comp - объект этого класса сравнения, а a и b - элементы контейнера [...] .Это может быть либо класс, реализующий оператор вызова функции, либо указатель на функцию [...] .

Я говорю о параметре шаблона Compare.

Таким образом, если бы я написал класс шаблона, который имеет параметр шаблона, который является классом, реализующим оператор вызова функции, я написал бы

template <class T, class Combine>
class MyClass
{
public:
    Combine func;
    MyClass()
    {
        func = Combine();
    }
    T do_it(T a, T b)
    {
        return func(a, b);
    }
};

class IntCombine
{
public:
    int operator () (int a, int b)
    {
        return a + b;
    }
};

//...
MyClass<int, IntCombine> ob;
ob.do_it(4, 5);

Или, если бы я написал его так,Второй параметр шаблона - это функция:

template <class T, T Combine(T, T)>
class MyClass
{
public:
    Combine func;
    MyClass()
    {
        func = Combine;
    }
    T do_it(T a, T b)
    {
        return func(a, b);
    }
};

int IntCombine(int a, int b)
{
    return a + b;
}

//...
MyClass<int, IntCombine> ob;
ob.do_it(4, 5);

Однако в STL вы можете использовать заданный класс в любом случае.Как это реализовано?Приведенный выше код работает, только если второй параметр шаблона в моем определении ob является либо классом, реализующим operator (), либо функцией, соответственно, но я не могу написать MyClass, чтобы оба они работали.

Мои примеры могут выглядеть довольно бесполезными.По сути, я хочу написать контейнер, который может объединять элементы, и такой же общий, как контейнеры STL.

1 Ответ

0 голосов
/ 13 января 2011

Приведенный выше код работает, только если второй параметр шаблона в моем определении ob является либо оператором реализации класса (), либо функцией, соответственно, но я не могу написать MyClass, чтобы оба работали.

Да, вы можете:

template <typename F>
struct foo {
    F f;
    void call() {
        f();
    }
};

void function() {
    std::cout << "function called" << std::endl;
}

int main() {
    foo<void(*)()> a = { function };
    a.call();
}

Это точно соответствует примеру конструктора std::set .Важным моментом является то, что если вы используете указатель на функцию, то параметром шаблона является , а не указателем на функцию, это тип указателя на функцию (здесь void (*)()).Вы должны хранить фактический указатель функции отдельно.

...