Как передать std :: sqrt в качестве аргумента - PullRequest
1 голос
/ 05 августа 2020

Я пытаюсь создать общую c функцию Foo, которая будет принимать аргумент и Op, что будет к нему применено.

template <template<class> class Op>   
float foo(float boo) {
    return Op(boo);
}

template <template<class> class Op>   
float foo(float a, float b) {
    return Op(a, b);
}

void caller() {
    float boo = 2.3;
    auto res1 = foo<std::plus>(boo, boo); // works
    auto res2 = foo<std::sqrt>(boo); // fail. error: no instance of overloaded function.
    auto res3 = foo<std::exp>(boo); // fail. error: no instance of overloaded function
}

Я думаю, это связано с тем, что std :: sqrt is

«Набор перегрузок или шаблон функции, принимающий аргумент любого целочисленного типа.»

, а std :: plus is

Функциональный объект для выполнения сложения.

Может кто-нибудь, пожалуйста, помогите исправить это? Как передать std::sqrt и std::exp на foo?

Ответы [ 3 ]

3 голосов
/ 05 августа 2020

std::sqrt - это перегруженная функция, а не тип. Простым исправлением было бы написать общую c лямбду, которая обертывает std::sqrt, а затем использовать ее тип при вызове foo, например:

auto sqrt = [](auto n) { return std::sqrt(n); };
auto res2 = foo<decltype(sqrt)>(boo); // ok

И вы можете сделать то же самое для std::exp.

Хорошее ли это исправление зависит от того, как вы хотите использовать параметр Op, что не ясно из вопроса.

3 голосов
/ 05 августа 2020

Как вы определили, проблема в том, что ваш шаблон ожидает тип (потому что вы его написали именно так), и хотя std::plus является типом (функтором), std::sqrt - это функция.

Трудно дать конкретное решение вашей проблемы, потому что вы никогда не показывали свое использование Op.

Но, как правило, это легко сделать с помощью auto параметр шаблона:

template <auto Op>
float foo(const float boo) {
    return Op(boo);
}

Если ваша версия C ++ слишком старая, вам нужно будет добавить версию, которая принимает вместо нее указатель на функцию.

2 голосов
/ 05 августа 2020

Вы не можете передать набор перегрузки в качестве аргумента шаблона. Простой обходной путь может заключаться в том, чтобы обернуть sqrt и exp в функторы с помощью шаблона operator():

struct Sqrt {
    template<class T>
    T operator()(T t) const { return std::sqrt(t); }
};

struct Exp {
    template<class T>
    T operator()(T t) const { return std::exp(t); }
};

Тогда будет работать следующее:

    auto res2 = foo<Sqrt>(boo);
    auto res3 = foo<Exp>(boo);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...