是否有一种通用方法可以将函数模板改编为多态函数对象?

发布于 2024-11-28 22:58:07 字数 806 浏览 4 评论 0原文

例如,我有一些函数模板,

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()) 传递。但这需要为我的每个函数模板编写一个单独的适配器。

是否有一种通用方法将函数模板调整为多态函数对象,即我可以为我需要调整的每个函数模板重复使用某种机制,而无需单独声明某些内容对于每一个?

I have some function templates, for example

template <typename T>
void foo(T);

template <typename T>
void bar(T);

// others

and I need to pass each one to an algorithm that will call it with various types, e.g.

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

I can't pass in my function template uninstantiated, but I can't instantiate it with any specific type either because some_algorithm will need to call it with arguments of several different types.

I could adapt my function templates to be polymorphic function objects, e.g.

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

and then pass it as some_algorithm(foo_polymorphic()). But this requires writing a separate adapter for each of my function templates.

Is there a generic way of adapting a function template to be a polymorphic function object, i.e. some mechanism that I can re-use for each of the function templates I need to adapt, without having to declare something separately for each one?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

骄兵必败 2024-12-05 22:58:07

问题的简短版本被赋予一个重载名称 f,如何简洁地编写一个对象 ff 使得 ff(a0, a1, a2, ... ) 最终调用 f(a0, a1, a2, ...)

多态函子,你如何指出自己,是通常的解决方案。但它必须被定义为不符合要求(因为它有一个模板成员),所以我认为这对于我的答案来说不够简洁。

目前 lambda 表达式产生一个单态函子,因此它们很接近,但还不够。

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

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

正如 GMan 在评论中指出的那样,多态 lambda 将(应该?)成为简洁地内联编写多态函子的解决方案。

同时,可以编写一个 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); } ); 。然而,我怀疑存在数量限制(因此是第一个宏参数),这与通常的外线手写多态函子解决方案不同;所以这对例如可变参数函数模板没有帮助。

The short version of the problem is given an overloaded name f, how to concisely write an object ff such that ff(a0, a1, a2, ...) ultimately calls f(a0, a1, a2, ...).

A polymorphic functor, how you point out yourself, is the usual solution. But it must be defined out of line (since it has a template member), so I'll consder that not concise enough for the purposes of my answer.

Currently lambda expressions yield a monomorphic functor, so they're close but not quite there.

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

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

As GMan pointed out in the comments polymorphic lambdas would (should?) be the solution to concisely write polymorphic functors inline.

In the meantime, it is possible to write a make_overload helper that combines multiple functors into one, such that

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

would 'capture' the whole overload set. Perhaps a Boost.Preprocessor macro could help here, so that auto ff = POLYMORPHIC_LAMBDA( 1, (int)(double), { return f(arg0); } ); be used inline. I suspect there are arity restrictions however (hence the first macro argument), unlike the usual out-of-line hand-written polymorphic functor solution; so this wouldn't help with e.g. variadic function templates.

笑梦风尘 2024-12-05 22:58:07

为什么不能使用模板模板参数?你说你不能在未实例化的情况下传递你的模板,但我不确定你以前是否听说过这个,请告诉我你是否听说过,但它不会起作用。

我不知道你的代码结构是什么样的,但是你能做类似的事情吗

我知道这有效,但不知道这是否是你想要的:

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

Why couldn't you use template template parameters? You said you can't pass your template uninstantiated, but I'm not sure if you've heard of this before, tell me if you have and it won't work.

I don't know what your code structure looks like, but can you do something like

I know this works, don't know if it's what yo uwant though:

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();
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文