16

考虑一下这个简单而毫无意义的代码。

#include <iostream>

struct A {
    template<int N>
    void test() {
        std::cout << N << std::endl;
    }
};

int main() {
    A a;
    a.test<1>();
}

这是一个非常简单的函数模板示例。但是,如果我想A::test用重载替换operator()它以使其成为仿函数怎么办?

#include <iostream>

struct A {
    template<int N>
    void operator()() {
        std::cout << N << std::endl;
    }
};

int main() {
    A a;
    a<1>(); // <-- error, how do I do this?
}

当然如果operator()取了依赖于模板的参数,编译器就有可能推导出模板。但我只是想不出用无参数仿函数指定模板参数的正确语法。

有没有合适的方法来做到这一点?

显然,这段代码可以工作,因为它绕过了仿函数语法:

a.operator()<1>();

但这有点违背了它成为函子的目的:-P。

4

5 回答 5

29

你只能打电话

a.operator()<1>();

但这不会使用仿函数。Functors 需要一个非模板 operator(),因为它们必须能够被称为varname()并且不适用于您的代码。

要使其成为真正的仿函数,请将您的代码更改为模板类(仿函数是类):

#include <iostream>

template<int N>
struct A {
    void operator()() {
        std::cout << N << std::endl;
    }
};

int main() {
    A<1> a;
    a();
}
于 2009-06-02T22:21:55.430 回答
10

除了以下之外,我没有其他“直接”方式:

 a.operator()<1>();

句法。如果您愿意更改代码,将模板参数移动到类中会起作用,或者使用 (boost|tr1)::bind 来创建 (boost|tr1)::function 对象。

于 2009-06-02T22:17:25.750 回答
2

您正在尝试将模板参数传递给对象的实例,据我所知这是不允许的。您只能将模板参数传递给模板函数或模板对象。

a.test<1>(); 和 a.operator()<1>(); 工作,因为它们充当模板功能。

使用 boost::bind (查看 boost 库)来修复它。

struct A {
    void operator()(int n) {
        std::cout << n << std::endl;
    }
};

int main(int argc, char* argv[]) {
    A a;
    boost::function<void()> f = boost::bind<void>(a, 1);
    f(); // prints 1

    return 0;
}

而且您甚至不必弄乱模板!

于 2009-06-02T22:23:00.700 回答
1

你被困住了。你有没有考虑过类似的东西

struct A {
    template<int N>
    struct B
    {
        void operator()()
        { std::cout << N << std::endl; }
    };

    template<int N>
    B<N> functor() {return B<N>();}
};

int main()
{
    A a;
    a.functor<1>()();
}
于 2009-06-02T22:26:58.023 回答
0

不,没有办法解决它。就像您说的那样,您必须显式调用运算符(这违背了目的),或者模板参数必须能够由编译器推导出来。

于 2009-06-02T22:24:06.003 回答