推导成员函数的参数列表

Deducing parameter list of a member function

我们希望能够推断出模板中成员函数调用的参数列表。这是一个更大项目的一部分,该项目最终执行允许调用目标函数的类型转换。

我们的研究得出了 ,这对我们帮助很大。

我们现在一直在为成员函数寻找类似的概念。关键元素在以下 Source 1 代码示例中:

查看演示我们当前研究的第二个代码块:我们知道函数和成员指针之间的区别,并且调用成员需要对象标识。但是我们无法用代码表达我们的知识。第二个代码块没有编译。

获得所示符号的正确符号和模板推导结构是什么?

来源 1

#include <iostream>

void free_funct(int p1, double p2) {
    std::cout << "p1=" << p1 << " p2=" << p2 << endl;
}

struct object {
    void object_funct(double p1, int p2) const {
        std::cout << "p1=" << p1 << " p2=" << p2 << endl;
    }
    int exec(double p1, int p2) {
        // Ultimate goal:
        // Wrapper<(???::object_funct> functor3;
        // functor_3(p1, p2;)
    }
};

template <auto F>
class Wrapper {};

template <typename R, typename... Args, auto (F)(Args...)->R>
struct Wrapper<F>
{
    auto operator()(Args... args) const -> R {
        return F(args...);
    }
};

int main() {
    // Free funct.
    Wrapper<free_funct> functor1{};
    functor1(313, 3.141592);
    object object;
    // Extrinsic call to member function.
    object.object_funct(3.1415926, 313);
    // Problem 1:
    Wrapper<&object::object_funct> functor2;
    // How to express this below
    // functor2(3, 1415926, 313);
    object.exec(2.718281, 121);
    return 0;
}

源代码 2(不编译)

template <auto F>
struct Wrap;
template <typename T, typename R, typename ... Args, R(T::* F)(Args...)>
struct Wrap<F> {
    auto operator()(Args... args) {
        return F(args...);
    }
};

struct foo {
    int bar(float) { 
        return 1; };
};

int main() {
    foo x;
    Wrap<&x::bar> f;
    f(3.14159265);
    return 0;
}

既然您希望Wrapper通过模板参数包装成员函数指针,您必须知道如何调用成员函数指针。通常我们使用(obj.*mfptr)(args...)(optr->*mfptr)(args...)调用成员函数指针,显然对象本身也是调用操作所必需的。所以在 Wrapper::operator() 中,我们不仅需要每个参数,还需要对象。

template <auto F>
struct Wrapper;
template <typename T, typename R, typename ... Args, R(T::* F)(Args...)>
struct Wrapper<F> {
    // it seems you don't take care of the cvref qualifiers, so I won't write all the overloads.
    auto operator()(T obj, Args... args) {
        return (obj.*F)(args...);
    }
    auto operator()(T* obj, Args... args) {
        return (obj->*F)(args...);
    }
};

实际上,成员函数调用与将对象作为第一个参数的函数调用相似(而不是等于)。所以你必须这样称呼它:

Wrapper<&foo::bar> f;
f(foo{}, 3.14);

编辑: 现在您还希望包装实例,Wrapper 必须使用实例构造:

template <auto F>
struct Wrapper;
template <typename T, typename R, typename ... Args, R(T::* F)(Args...)>
struct Wrapper<F> {
    // I also omit the overloads of pass by reference semantics.
    Wrapper(T obj) :instance(std::move(obj)){}

    auto operator()(Args... args) {
        return (instance.*F)(args...);
    }
private:
    T instance;
};

int main(){
    foo x;
    Wrapper<&foo::bar> f{x};
    f(3.14);
}