Подтвердить что ты не робот

Существует ли общий способ адаптации шаблона функции к объекту полиморфной функции?

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

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

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

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

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

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

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

4b9b3361

Ответ 1

В короткой версии проблемы задано перегруженное имя 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 в комментариях, полиморфные лямбда были бы (должны?) быть решением для краткой записи полиморфных функторов inline.

В то же время можно написать вспомогательный элемент 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); } ); будет использоваться inline. Однако я подозреваю, что существуют ограничения на arity (следовательно, первый макро-аргумент), в отличие от обычного внекорневого рукописного полиморфного функторного решения; так что это не помогло бы, например, шаблоны вариационной функции.

Ответ 2

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

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

Я знаю, что это работает, не знаю, насколько это уместно:

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();
}