使用模板应用功能模板

Use template to apply a function template

如果以下示例是 C++,它将包含无意义的乱码,因此我将定义该示例以伪代码编写(因此是正确的)。它强烈暗示了我想用 C++ 做什么。

#include <vector>

template<class T>
void increment(T& x)
{
    ++x;
}

template<template<class> class F>
struct Apply
{
    template<class T>
    void operator()(std::vector<T>& v)
    {
        for (auto& x : v)
            F<T>(x);
    }
};

template<template<class> class F, class T>
void apply(F<T> f, std::vector<T>& v)
{
    for (auto& x : v)
        f(x);
}

int main()
{
    std::vector<int> v{1,2,3};

    // apply increment function to v

    // maybe this?
    Apply<increment> a;
    a(v);

    // hmm... or this?
    apply(increment, v);
}

我不知道如何将其转换为 C++,以便:

  1. increment 是函数而不是函数对象。

  2. increment的参数由Apply/apply推断或提供。

  3. Apply/apply 不知道名字 increment.

我可以满足三个中的两个,但我不确定如何同时满足所有三个。我 运行 遇到的问题是显然需要使用函数模板作为我的编译器不喜欢的模板模板参数。尽管如此,即使该特定路线是禁区,它似乎也确实有可能工作。

如何做到?

编辑: 我讨厌更改问题,但我没有很好地尝试正式陈述需求。假设您是 apply 的作者,但您不是 increment 的作者。你被 increment 困住了。

简单:放弃全部。

template<class F, class T>
void apply(T& v, F f)
{
    for (auto& x : v)
         f(x);
}
int main()
{
    std::vector<int> v{1,2,3};
    apply(v, [](int& i) { ++i; });
    auto a = [](std::vector<int>& v) {
         apply(v, [](int& i) { ++i; });
    };
    a(v);
}

你只是在重新发明 lambda,但更糟。 C++ 中的函数式编程最好使用函数对象来完成,因为常规函数具有 shit 语义,并且我们具有明确的语言特性,目的是为了轻松制作函数对象,因此请使用它们。

正如一位评论者所指出的,这也基本上只是 std::transform 但过于具体,而且 std::transform 也可以采用 lambda。

不要费心尝试使用传递函数来实现功能 - 这是无法完成的,至少在具有竞争力的代码质量和数量的情况下无法做到。使用函数对象,尤其是 lambda。这正是他们的目的。

您似乎混淆了函数的类型和函数本身。 在这种情况下写 Apply<increment> 没有意义,因为 increment 是函数的名称而不是它的类型。 此外,如果不指定模板类型,就不能使用这样的模板函数。但解决方法是改用通用 lambda。

这是一个工作示例

#include <vector>
#include <iostream>

using std::cout;
using std::vector;

template<class T>
void increment(T& x)
{
    ++x;
}

template<class T>
void print(const T& t) {
    for(auto&& v : t)
        cout << v << " ";
    cout << std::endl;
}

template<typename T, typename F>
void apply(T& container, F function) {
    for(auto& v : container) {
        function(v);
    }
}

int main()
{
    vector<int> v{1,2,3};
    print(v);
    // To retrieve a function pointer you must specify the type
    apply(v, &increment<int>);
    print(v);
    // If your using c++14 you can use a generic lambda
    apply(v, [](auto& t) { increment(t); });
    print(v);
}