Question

I'm using a library with a defective operator<<, which I want to replace with my own version. It follows the idiom where ADL selects the overload based on the argument's membership in the library's namespace. Is there any way to cause C++ to select my own operator<< instead?

Was it helpful?

Solution

One suboptimal solution is to declare a wrapper class around the library type.

A general implementation would look like this:

/* Namespace-specific reference wrapper type.
   Associates a function argument with the desired namespace.
   Declare a new use_local_t for each namespace with an overriding overload */
template< typename t >
struct use_local_t
    { t ref; };

template< typename t >
use_local_t< t && >
use_local( t &&o )
    { return { std::forward< t >( o ) }; }

/* The overriding overload.
   Instead of overloading on a specialization of use_local_t, use the
   general template and enable_if. This allows for the various kinds of
   references that use_local_t might forward, and conversion of the function
   argument to the expected library_type parameter. */
template< typename t >
inline
typename std::enable_if<
    std::is_convertible< t, library_type const & >::value,
    std::ostream &
>::type
operator<< ( std::ostream &s, use_local_t< t > ul ) {
    return s << ul.ref.foo;
}

std::cout << my_namespace::use_local( library_obj );

This is tested to work with expression templates. Note that if the override overload doesn't match, the error message from GCC 4.7 is a red herring… it refers to an overload in std:: involving a stream rvalue reference:

/opt/local/include/gcc47/c++/ostream:600:5: error: initializing argument 1 of 'std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top