当前位置: 首页 > 知识库问答 >
问题:

具有任何参数的模板函子

杜鸿彩
2023-03-14

我正在尝试创建一个模板函子,它将使用任意数量的参数作为参数对象和成员函数。我不知道如何用模板正确地编写代码。

template<typename ItemT,
     class T,
     typename ...Args>
struct Builder
{
    ItemT operator()(T& object, ItemT (T::*method)(Args...), Args && ... args)
    {
        return (object.*method)(std::forward<Args>(args)...);
    }
};

struct Object
{
    int method(int, int, int) { return 4; }
};


int main()
{
    Object obj;    
    Builder<int, Object>()(obj, &Object::method); // Error here
}

如果我使对象::方法没有参数-代码编译。但是有参数-没有。

严重性代码描述项目文件行抑制状态错误C2664'int Builder::运算符()(T

共有2个答案

荣波
2023-03-14

您可以完全避免在<code>生成器

struct Builder {
    template <typename Obj, typename R, typename ... FArgs, typename ... Args>
    R operator()(Obj& obj, R (Obj::*fn)(FArgs...), Args&&... args) {
        return (obj.*fn)(std::forward<Args>(args)...);
    }
};

我选择使用两个参数包来实现完美的转发:operator()调用的值类别不一定与目标方法匹配。这也允许在应用成员函数指针时隐式转换参数。请注意,此实现将与 Objconst 方法不匹配。

当然,您可以使用自动返回类型(C 14)或尾随返回类型(C 11)稍微放松一下。由于Vittorio的答案已经向您展示了C 14的方式,我将解决后者。然后,运算符 () 将变为:

template <typename Obj, typename FnPtr, typename ... Args>
auto operator()(Obj& obj, FnPtr fn, Args&&... args)
    -> decltype((obj.*fn)(std::forward<Args>(args)...)) {
    return (obj.*fn)(std::forward<Args>(args)...);
}

那么,用法就简单了:

Object obj;
Builder()(obj, &Object::method, 0, 0, 0);

在Coliru上的现场演示

爱琪
2023-03-14

假设您不想更改生成器的当前定义,则需要这样实例化它:

Builder<int, Object, int, int, int>()(obj, &Object::method, 0, 0, 0);
//      ^       ^    ^^^^^^^^^^^^^                          ^^^^^^^
//      ItemT   |    |                                      |
//              T    Args...                                args...

< code >参数... < code > operator()调用中的参数扩展必须与< code >目标匹配...包传递给< code >生成器本身。

wandbox示例

这里有一个不太严格的替代设计:

template<typename T>
struct Builder
{
    template <typename TFnPtr, typename... Args>
    auto operator()(T& object, TFnPtr method, Args && ... args)
    {
        return (object.*method)(std::forward<Args>(args)...);
    }
};

上面的Builder可以这样使用:

int main()
{
    Object obj;    
    Builder<Object>()(obj, &Object::method, 0, 0, 0);
}

在这种情况下,成员函数指针的类型是通过TFnPtr推导出来的,并且不受任何特定参数集的约束。可变参数不再是Builder的一部分-它们是Builder::运算符()的一部分,因此它们可以被推导并转发到(对象。*方法)

wandbox示例

 类似资料:
  • 是否允许在友元声明中为模板参数提供默认值? Visual Studio 2015似乎允许这样做。gcc拒绝了。我在cppreference页面上找不到任何内容。

  • 我对编程和C++相当陌生。我有一个函数,我想接受以模板化值作为参数的函数指针。我的意思是... 我有这个功能: 我试过的: 结果: .h:165:22:注意:已忽略候选模板:无法将“function ,allocator >&)”与“void(*)(bool,std::vectorstd::vectorstd::allocatorstd::tuple &)”void postgrescaller:

  • 我想在模板类之外定义如下所述的函数。 已经为第二个参数尝试了很多组合,它是一个模板,并且也接受默认参数。 我希望它是在类之外定义的实际得到编译器错误,如果它是简单的类型,我可以很容易地在第二个参数中提到int、浮动等。

  • 如果我没有理解错的话,类模板定义了一个函数,所以当我调用时,编译器有可能进行隐式强制转换,但是在函数模板的情况下,此时没有函数定义,所以隐式强制转换不会发生。 但我不明白为什么编译器不能创建函数定义,然后应用隐式强制转换? 错误是: 在函数“int main()”中:    25:24:错误:调用“test2::add(void(&)(int))”没有匹配函数    25:24:注:候选人是:  

  • 在C++11之前,类模板和函数模板只能含有固定数量的模板参数。C++11增强了模板功能,允许模板定义中包含0到任意个模板参数,这就是可变参数模板。可变参数模板的加入使得C++11的功能变得更加强大,而由此也带来了许多神奇的用法。 可变参数模板 可变参数模板和普通模板的语义是一样的,只是写法上稍有区别,声明可变参数模板时需要在typename或class后面带上省略号...: template<ty

  • 问题内容: 我正在向Django的模板传递一个函数,该函数返回一些记录。我想调用此函数并遍历其结果。 那不行 我试图将函数的返回值设置为变量并遍历该变量,但是似乎没有办法在Django模板中设置变量。 有什么正常的方法吗? 问题答案: 你不能调用在模板中需要参数的函数。写一个模板标签或过滤器。