Find overload address only by its parameters

Assuming that a function (which can be either a global function or a member function) is overloaded only by its parameters (so that its overloads will always be all const or all non-constant). Is there a way to write a template that will select the overload address according to the specified parameter? For instance:

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; 

An interesting answer that I found here , but, unfortunately, it only deals with forwarding the call to the correct overload, and not actually choosing the overload address, it can be used later.

One final note: the perfect solution should work on the released version of Clang. In addition to this requirement, you can use any available functions C ++ 1z and below.

+5
source share
3 answers

Before you can access the address of an overloaded function, you must indicate which version you need.

 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); } 
+1
source

You can use static_cast<>() :

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

Despite @MRB's working answer , there is a more compact solution.
This follows a minimal working example:

 #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); } 

As you can see, find_overload accepts both free functions and member functions (for which it infers the class type as well as the return type).

0
source

Source: https://habr.com/ru/post/1262836/


All Articles