Search code examples
c++typedefargument-dependent-lookup

ADL with typedefs from another namespace


I have something like this:

#include <iostream>
namespace N
{
   typedef std::pair<int, double> MyPair;
   std::ostream& operator << (std::ostream& o, MyPair const & mypair)
   {
      ///
   }
}

int main()
{
    N::MyPair pr;
    std::cout << pr;
}

This naturally doesn't work, because ADL won't find operator<< because namespace N is not associated with MyPair (unfortunately). Afaik one may not add to namespace std, so if I chose to define operator << in std that would be kinda illegal. So... what to do in such situations? I don't want to explicitly qualify operator <<, nor do I wish to write using namespace N. So, questions are:

  1. How to refactor the code?
  2. Why wouldn't ADL associate namespaces of typedefs? Serious reasons? It would be nice, e.g. in this case. Thanks

Solution

    1. You could create your own type in namespace N, possibly inheriting from std::pair. You could add "using namespace N;" inside main. The former is more likely to be useful.

    2. Because the type is defined in another namespace and cannot be defined in two.

    Example:

    namespace N { 
    struct MyPair : std::pair<int, double> {
      MyPair(int first, double second) : std::pair<int, double>(first, second) {}
      // add defaults if desired: first=0, second=0.0
      // with defaults, you may want to make the ctor explicit or leave implicit
    
      // also, if desired and you don't use two defaults above:
      MyPair() : std::pair<int, double>(0, 0.0) {}
    
      // in 0x, you can "import" the base's ctors with a using declaration
    };
    }
    

    If being used as a std::pair isn't important, you can drop the inheritance and rename the members. In either case you can, of course, add additional methods, but if you keep the inheritance you can use "renaming methods":

    int      & foo()       { return first; }
    int const& foo() const { return first; }
    double      & bar()       { return second; }
    double const& bar() const { return second; }