使用模板应用函数模板

时间:2015-02-28 11:10:07

标签: c++ templates c++11 c++14

如果以下示例是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

  4. 我可以满足三个中的两个,但我不确定如何同时满足所有三个。我遇到的问题是显然需要使用函数模板作为我的编译器不喜欢的模板模板参数。尽管如此,即使特定路线不受限制,它似乎也有可能实现这一点。

    怎么做?

    编辑:我讨厌改变问题,但我并没有做出正式声明要求的工作。只是假装你是申请的作者,但你不是increment的作者。您按原样坚持increment

2 个答案:

答案 0 :(得分:2)

简单:放弃全部。

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

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

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

不要试图通过功能来实现功能 - 它无法完成,至少不具备竞争性的代码质量和体积。使用函数对象,尤其是lambdas。这实际上就是他们的目的。

答案 1 :(得分:2)

你似乎混淆了函数的类型和函数本身。 在这种情况下编写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);
}