仅通过其参数查找重载地址
Find an overload address by its parameters only
假设一个函数(可以是全局函数或成员函数)仅在其参数上重载(因此它的重载将始终全部为 const 或全部为非 const)。有没有办法写一个模板,根据指定的参数select重载地址?例如:
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;
我发现的一个有趣的答案是 here,但不幸的是,它只处理将调用转发到正确的重载,而不是实际获取重载地址以便稍后使用。
最后一点:完美的解决方案应该适用于已发布的 Clang 版本。除此要求外,还可以使用任何可用的 C++1z 功能和更低版本。
您可以使用 static_cast<>()
:
auto addressDouble = static_cast<double(*)(double, double)>(&Foo:bar);
auto addressInt = static_cast<int(*)(int, int)>(&Foo:bar);
在您可以访问重载函数的地址之前,您必须指定您需要哪个版本。
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);
}
尽管@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
接受自由函数和成员函数(它推导出 class 类型和 return 类型)。
假设一个函数(可以是全局函数或成员函数)仅在其参数上重载(因此它的重载将始终全部为 const 或全部为非 const)。有没有办法写一个模板,根据指定的参数select重载地址?例如:
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;
我发现的一个有趣的答案是 here,但不幸的是,它只处理将调用转发到正确的重载,而不是实际获取重载地址以便稍后使用。
最后一点:完美的解决方案应该适用于已发布的 Clang 版本。除此要求外,还可以使用任何可用的 C++1z 功能和更低版本。
您可以使用 static_cast<>()
:
auto addressDouble = static_cast<double(*)(double, double)>(&Foo:bar);
auto addressInt = static_cast<int(*)(int, int)>(&Foo:bar);
在您可以访问重载函数的地址之前,您必须指定您需要哪个版本。
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);
}
尽管@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
接受自由函数和成员函数(它推导出 class 类型和 return 类型)。