Как обработать значение по умолчанию для шаблонного функтора - PullRequest
3 голосов
/ 11 октября 2011

С учетом такой функции:

template<typename functor>
void foo(functor const& f)
{
    if (f)
        f(1, 2);
}

Я хочу иметь возможность назначить значение по умолчанию, где f может быть установлено на что-то подобное NULL. Кроме того, было бы достаточно сделать фиктивный вызов пустой функции. Могу ли я использовать что-либо (из стандартной или boost -библиотеки), не создавая такого самостоятельно?

Ответы [ 7 ]

9 голосов
/ 11 октября 2011

Использовать пустой функтор и использовать в качестве параметра шаблона по умолчанию. Вы не можете использовать что-то вроде NULL, потому что у вас нет указателя:

class X
{
    void operator()(...) {}
};

template <typename functor = X>
void foo(functor const& f = X())
{
    f(...);
}
3 голосов
/ 11 октября 2011

Либо напишите перегрузку, которая принимает и ничего не делает, либо передайте неоперативный функтор на foo.

2 голосов
/ 11 октября 2011

Самый простой способ - создать перегрузку без аргументов:

template<typename functor>
void foo()
{
}

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

1 голос
/ 09 сентября 2014

Я использую это как бездействие для случаев, когда я ожидаю, что функтор не возвращает никакого значения.

struct VoidNoOp {
    void operator()() const { }
    template<class A>
    void operator()(A a) const { (void)(a); }
    template<class A, class B>
    void operator()(A a, B b) const { (void)(a); (void)(b); }
    template<class A, class B, class C>
    void operator()(A a, B b, C c) const { (void)(a); (void)(b); (void)(c); }
};

Вот вариант C ++ 11 для произвольного числа параметров:

struct VoidNoOp {
    void operator()() const { };
    template<typename P1, typename... Params>
    void operator()(P1 p1, Params... parameters) {
        (void)(p1);             // we do this just to remove warnings -- requires the recursion
        operator()(parameters...);
    }
};
1 голос
/ 11 октября 2011

Я не хочу использовать перегруженные функции. Кажется, использование самописного «nop-класса» - лучшее решение.

struct nop
{
    void operator()(...) const volatile {}
};

template<typename functor> 
void foo(functor const& f = functor()) 
{
    f(1, 2);
}

int main()
{
    foo<nop>();
    return 0;
}
0 голосов
/ 11 октября 2011

Оболочка функции, которая может хранить NULL во время выполнения, имеет вид std::function (C++11) или boost::function.

#include <functional>
#include <cstdio>

void foo(std::function<void(int, int)> f)
{
    if (f) {
       f(1, 2);
    }
}

void print(int a, int b) { std::printf("%d %d\n", a, b); }

int main()
{
   foo(0);
   foo(print);
}
0 голосов
/ 11 октября 2011

Проблема в том, что functor - это тип, определяемый вызывающей стороной, поэтому он может не иметь конструктора по умолчанию или каких-либо других функций, на которые вы полагаетесь при создании значения по умолчанию.

Итак, можете ли выиспользовать перегруженную функцию?

template<typename functor>
void foo(functor const& f)
{
       f(1, 2);
}

template<typename functor>
void foo()
{
}
...