仅通过参数查找重载地址

Find an overload address by its parameters only

本文关键字:重载 地址 查找 参数      更新时间:2023-10-16

假设一个函数(可以是全局函数或成员函数)仅在其参数上重载(因此其重载将始终是所有常量或所有非常量)。有没有办法编写一个模板,根据指定的参数选择重载地址?例如:

struct Foo {
    double bar(double n, double m);
    int bar(int n, int m);
};
auto addressDouble = find_overload<&Foo::bar, double, double>::address;
auto addressInt = find_overload<&Foo::bar, int, int>::address;

我在这里找到了一个有趣的答案,但不幸的是,它只处理将调用转发到正确的重载,而不是实际获取重载地址以便以后可以使用。

最后一点:一个完美的解决方案应该适用于已发布的 Clang 版本。除此要求外,还可以使用任何可用的 C++1z 及更低功能。

在访问重载函数的地址之前,您必须指定需要哪个版本。

template<typename ...TA>
struct find_overload
{
    template<typename TObj, typename TR>
    using member_func_t = TR(TObj::*)(TA...);
    template< typename TObj, typename TR >
    static constexpr auto get_address(member_func_t<TObj, TR> func) -> member_func_t<TObj, TR>
    {
        return func;
    }
};
int main()
{
    constexpr auto address = find_overload<double, double>::get_address(&Foo::bar);
}

您可以使用static_cast<>()

auto addressDouble = static_cast<double(*)(double, double)>(&Foo:bar);
auto addressInt = static_cast<int(*)(int, int)>(&Foo:bar);

尽管@MRB的工作答案,但存在更紧凑的解决方案。
它遵循一个最小的工作示例:

#include<iostream>
struct Foo {
    double bar(double n, double m) {}
    int bar(int n, int m) {}
};
double quux(double n, double m) {}
int quux(int n, int m) {}
template<typename... A, typename T, typename R>
constexpr auto find_overload(R(T::*f)(A...)) { return f; }
template<typename... A, typename R>
constexpr auto find_overload(R(*f)(A...)) { return f; }
int main() {
    auto fooAddressDouble = find_overload<double, double>(&Foo::bar);
    auto fooAddressInt = find_overload<int, int>(&Foo::bar);
    Foo foo;
    (foo.*fooAddressDouble)(0., 0.);
    (foo.*fooAddressInt)(0, 0);
    auto globalAddressDouble = find_overload<double, double>(&quux);
    auto globalAddressInt = find_overload<int, int>(&quux);
    globalAddressDouble(0., 0.);
    globalAddressInt(0, 0);
}

如您所见,find_overload 同时接受自由函数和成员函数(它推导类类型和返回类型)。