Boost logo

Boost :

Subject: [boost] Boost.Operators issue: polluting namespace of caller through argument-dependent lookup
From: John M. Dlugosz (mpbecey7gu_at_[hidden])
Date: 2016-01-17 04:51:27


Here's the problem I ran into
http://stackoverflow.com/questions/34449254/how-is-argument-dependent-lookup-looking-here

|usingstd::tr1::shared_ptr; ||usingstd::tr1::make_shared;|

|shared_ptr<Dog>Gamma::knockout (constHotel&target){Eggsoftboiled
(target.ID);softboiled.sequence
^=0x40000000;returnmake_shared<Dog>(softboiled,target.kin,Frank::myself());} |

The arguments to the constructor passed through make_shared are of types

|Able::Bravo::Charlie::Egg&,constuint32_t&,constFrank&|

The use of make_shared is finding boost::make_shared as well as std::make_shared. The
program doesn't use boost::shared_ptr and shouldn't need to know about it.

It turns out that Frank is derived privately from boost::totally_ordered1 (and and Egg
from boost::totally ordered).
Some Boost header that's being used in this translation unit just happens to pull in
Boost's shared_ptr stuff. It ends up effectively polluting the namespace of possible
calls involving these types, thanks to argument-dependent lookup.

Furthermore, which Boost headers include which will change from version to version. I
have this problem show up much more in Boost 1.60 than I have in Boost 1.59. There is no
easy way around it beyond qualifying the call make_shared, and I specifically want to
avoid that so I don't litter the program with tr1's (this varies by compiler and version
as to whether tr1 is required, prohibited, or optional, so I want it in one place.)

I believe the proper thing to do, which is a very simple fix actually, is to define the
mix-in classes like totally_ordered (and other things from Boost.Operators in particular)
in a unique inner namespace, and then make aliases in the boost namespace where they are
published as being found.

     namespace boost {

*namespace inner_name_1 { *

         template<typename T, Typename U>
         partially_ordered { ⋯ };

         // the entire guts of Boost.Operators can go here, I think.

*} // end of inner isolating namespace**
**
** using inner_name_1::partially_ordered;*
     // etc.
     }

This inner isolation technique should be SOP for any classes that are meant to be
inherited from by user (non-Boost library) code.
It would not hurt to also isolate classes that match the names of std library code, in
general! This would, in general, prevent the libraries from interfering with each other
and surprises popping up when using std components and pulling in Boost headers.

—John

||


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk