Есть ли общий способ приспособить шаблон функции к объекту полиморфной функции? - PullRequest
12 голосов
/ 12 августа 2011

У меня есть несколько шаблонов функций, например

template <typename T>
void foo(T);

template <typename T>
void bar(T);

// others

и мне нужно передать каждый алгоритм, который будет вызывать его различными типами, например

template <typename F>
void some_algorithm(F f)
{
    // call f with argument of type int
    // call f with argument of type SomeClass
    // etc.
}

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

Я мог бы адаптировать шаблоны своих функций к объектам полиморфных функций, например,

struct foo_polymorphic
{
    template <typename T>
    void operator()(T t)
    {
        foo(t);
    }
};

и затем передайте его как some_algorithm(foo_polymorphic()). Но для этого нужно написать отдельный адаптер для каждого из моих шаблонов функций.

Существует ли универсальный способ адаптации шаблона функции к объекту полиморфной функции, т.е. какой-то механизм, который я могу повторно использовать для каждого из шаблонов функций, которые мне нужно адаптировать, без необходимости объявлять что-то отдельно для каждого?

Ответы [ 2 ]

2 голосов
/ 12 августа 2011

Краткая версия проблемы имеет перегруженное имя f, как кратко написать объект ff такой, что ff(a0, a1, a2, ...) в конечном счете вызывает f(a0, a1, a2, ...).

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

В настоящее время лямбда-выражения дают мономорфный функтор, поэтому они 'близко, но не совсем.

// set of functions overloaded on int and double
void f(int);
void f(double);

auto ff = [](int i) { return f(i); };

Как указал GMan в комментариях, полиморфные лямбды были бы (должны?) решением для краткой записи полиморфных функторов в строке.

Между тем,можно написать помощник make_overload, который объединит несколько функторов в один, так что

auto ff = make_overload(
    [](int arg0) { return f(arg0); }
    , [](double arg0) { return f(arg0); } );

будет «захватывать» весь набор перегрузок.Возможно, здесь может помочь макрос Boost.Preprocessor, так что auto ff = POLYMORPHIC_LAMBDA( 1, (int)(double), { return f(arg0); } ); будет использоваться встроенным.Однако я подозреваю, что существуют ограничения арности (отсюда и первый аргумент макроса), в отличие от обычного внепланового решения, написанного от руки полиморфным функтором;так что это не поможет, например, с помощью шаблонов переменных функций.

1 голос
/ 12 августа 2011

Почему вы не можете использовать параметры шаблона шаблона? Вы сказали, что не можете передать свой шаблон необоснованно, но я не уверен, слышали ли вы об этом раньше, скажите мне, если у вас есть, и он не будет работать.

Я не знаю, как выглядит ваша структура кода, но вы можете сделать что-то вроде

Я знаю, что это работает, но не знаю, зачем тебе это:

template<typename T>
T some_algorithm(T data) { return T(); } // just returning nothing for example

template<typename T, T(*Something)(T)>
class FuncClass {
public:
    T run(T data) { return Something(data); }
};

template<typename T, typename Functor>
void apply_algorithm(T data) {
    Functor F;
    F.run(data);
}

int main() {
    int mydata = 4;
    apply_algorithm<int, FuncClass<int, some_algorithm<int> > >(mydata);

    cin.get();
}
...