C++中的模板化operator()重载

10

有人已经问了这个问题,但是讨论结束后原始的问题没有得到解答。

假设你有以下内容:

template<size_t i, class f_type>
void call_with_i(f_type f);

functor_type可以是以下两种之一:

a) 一个结构体,其中包含一个方法,该方法具有以下签名:

template<size_t i> operator()() const;

或者,一个长得像这样的函数:
template<size_t i> foo();

我希望"call_with_i<42>(foo)"相当于"foo<42>()",但我无法确定正确的语法。我会满意于只实现(a)的方案,但(a)+(b)的解决方案更好。我已经尝试了以下语法:
f< i >(); // doesn't work
f()< i >; // doesn't work
f.operator< i >(); // doesn't work
f.operator()< i >; // doesn't work
f.operator()< i >(); // works on msvc, but doesn't work on gcc. 

您如何使用显式模板参数调用operator()?有没有一种方法可以以调用模板化的自由函数的相同语法方式调用它?
附注:如果您想知道我正在使用它做什么,那是因为我正在编写一个函数repeat_to,其中repeat_to<10>(f)调用f(0),然后f(1)... f(10)。我使用这个函数来按索引并行迭代多个boost :: fusion向量。是的,我可以使用迭代器,或者我可以只使用命名成员函数,但我仍然想知道答案。
编辑注意:我划掉了一些东西,因为将模板化的自由函数作为参数传递毫无意义。

因为你无法回答,所以它没有被回答。 - GManNickG
3个回答

14

成员模板是一个依赖名称,因为其语义取决于f_type 的类型。这意味着您应该在其名称之前放置 "template"(以消除对 "less-than" 标记的歧义),类似于在依赖限定名称之前应该放置 typename

template<size_t i, class f_type>
void call_with_i(f_type f) {
  f.template operator()<i>();
  // f.template foo<i>();
}

作为解决方法,您可以使用一个辅助类型:

template<size_t N> struct size_t_ { }; // or boost::mpl::int_

template<size_t i, class f_type>
void call_with_i(f_type f) {
  f(size_t_<i>());
}

现在,您可以将operator()定义为以下内容:

template<size_t i> void operator()(size_t_<i>) const {
  // i was deduced automatically by the function argument. 
}

这在模板构造函数中非常有用,因为你不能像f_type()<i>()那样做。在这种情况下它们必须是可推断的。


@Johannes:为什么不使用SFINAE来专门化函数呢? - Konrad Rudolph
运行得很好!真是太棒了。你是我的元英雄。啊,你使用 mpl::int_ 的想法也很聪明。 - Glenn
@laulaulabs.mp,很高兴能帮忙 :) - Johannes Schaub - litb
我发现像@laulaulabs.mp一样尝试传递函数模板是没有意义的。因此,在这种情况下,使用size_t_的解决方法是值得怀疑的。相应地修改了答案。 - Johannes Schaub - litb

1
在您这种情况下,我会使用boost::function作为函数对象类型。这样,您可以同时传递函数对象和函数指针,同时保持相同的接口。

0
#include <iostream>

template<size_t i, class f_type> void call_with_i(f_type f);

struct A {

    template < size_t i >
    void operator()() const {
        /* no link err in demo */
    }

    template < size_t i >
    void foo() {
        /* no link err in demo */
    }
};

int main(int argc, char * const argv[]) {
    A f;

    enum { Constant = 42 };

    f.operator()<Constant>();
    f.foo<Constant>();

    return 0;
}

有没有一种方法可以以相同的语法调用模板化的自由函数呢?
你能澄清一下吗?(伪代码或其他什么东西)

实际上,我关于模板化自由函数的那一段纯属胡说八道,因为你无法将函数模板作为参数传递。 - Glenn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接