This is a well-known problem, and its solution is equally well known. I am surprised that it has not been mentioned yet. If you have a function other than a member, for example:
class C; size_t size( C const &c );
You can force the search name to find it in the preference of a member function with a using declaration:
struct B { size_t size(); void foo( C const &c ) { using ::size; size_t sz = size(c); } };
When the compiler sees a call to size(c) , it starts in the innermost area and looks outside for something called size . Without a using declaration, the compiler would detect a member function in the class area before a non-member in the global namespace, but this using declaration will change this. The scope itself is the function itself, and the declaration of use is found before the member function.
The beauty is that you still get an argument-dependent search (ADL), because the actual call to size(c) is unqualified. This means that you can use it in a template:
template <class T> void foo( T const &c ) { using ::size; size_t sz = size(c); }
... and even if the correct size function is in a different namespace, it will be found by ADL. The using declaration just has to refer to some size function, not necessarily the one you really want. It would be normal to have a default implementation somewhere that possibly calls the member. The next version of the C ++ standard (C ++ 17) almost certainly has a std::size function that does just that. When it is available, you can write
using std::size; size_t sz = size(c);
At the moment, you can either provide your own default implementation, for example:
template <class C> constexpr auto size( C const &c ) -> decltype(c.size()) { return c.size(); }
... or you can continue to reference the C version and rely on ADL to find the right one.
Richard Smith
source share