https://svn.boost.org/trac/boost/ticket/4515 Nasty naming conundrum? (Or does C++ need a 'not using ...; ' statement?)

https://svn.boost.org/trac/boost/ticket/4515 has uncovered a nasty example of name ambiguity caused by the addition of <random> to the Standard Library. As the Standard Library expands, it may not be the last:-( http://tinyurl.com/2blmq3l gives an example of details of the ambiguity of the name 'binomial_distribution'. "error: reference to ???binomial_distribution??? is ambiguous" Random library defines 'binomial_distribution' and so 'using namespace std;' brings this name into std scope implicitly because it is a library item name (explicitly if random is included or perhaps implicitly by some '#include <std>;' declaration). But Boost.Math also defines the name 'binomial_distribution' but in the namespace boost::math. So this implies that it may be necessary to fully qualify boost::math::binomial_distribution at all uses. Ugh! We don't want to add namespace qualifiers everywhere because it messes up the simplicity of the example, but without them the code *might not* compile on C++0x compilers depending upon whether <random> happens to get included or not. To my ignorant surprise, 'using boost::math::binomial_distribution;' does not trump 'using namespace std;', despite being explicit *if it is at global scope ()*. But 'using boost::math::binomial_distribution;' works as I expected only at *local* scope. (Is this right language gurus? It feels too complicated?) Solution are: 1 Always fully qualify names like "boost:math::binomial_distribution<> my_bd;' This is hideously verbose. 2 Use " std::cout;" etc (instead of "using namespace std;" and "cout <<..." , but it gets tediously verbose. 3 Use "using std::cout;" etc instead of "using namespace std;", so we can still write cout << .. << endl; I have always favoured this solution because it documents clearly which functions are being used, and avoids the tedium of writing 'std::cout;'. (And from habit - because "using namespace std;" seemed to cause trouble using early MSVC). But it does add some clutter and *must not be done at global scope in .hpp files* - because it would quietly commit all those who #include to this definition (which may not be what they want/expect). 4 Use "using boost:math::binomial_distribution;" at local scope (but NOT at global scope). (Include files could be used to make this less verbose if there a lots of functions?) 5 Use a namespace alias for boost::math:: to reduce the verbosity of Richards proposed fix with ticket/4515. This feels like a sticking plaster solution? and is still nearly as ugly is 'bm::binomial_distribution'. Overall, John Maddock and I having pondered the least worst solution and are inclined to recommend: a Avoid using global "using namespace anything;" b For each include like <iostream>, use "using std::cout;" statements at local scope for included .hpp files, and at global (or local) scope for source .cpp files (or always write the fully qualified "std::cout << ... "). c For each boost::math include, like "#include <boost:math::binomial_distribution>", provide a "using boost:math::binomial_distribution;" statements (at local scope for included .hpp files and at global (or local) scope for source .cpp files). This may seem an obscure problem, but are there likely to be increasing number of name clashes like this as libraries increase in number? Views? Paul PS My proposal for adding a "not using ... " statement to C++ has so far got a less than warm reception ;-) Paul A. Bristow, Prizet Farmhouse, Kendal LA8 8AB UK +44 1539 561830 07714330204 pbristow@hetp.u-net.com

On 31/08/2010 09:55, Paul A. Bristow wrote:
https://svn.boost.org/trac/boost/ticket/4515 has uncovered a nasty example of name ambiguity caused by the addition of<random> to the Standard Library. As the Standard Library expands, it may not be the last:-(
http://tinyurl.com/2blmq3l gives an example of details of the ambiguity of the name 'binomial_distribution'.
"error: reference to ???binomial_distribution??? is ambiguous"
Random library defines 'binomial_distribution' and so 'using namespace std;' brings this name into std scope implicitly because it is a library item name (explicitly if random is included or perhaps implicitly by some '#include<std>;' declaration).
Well yeah, if you pull two namespaces that contain the same names into the global namespace, you get collisions. The solution is easy: - don't do 'using namespace' - if you really insist, prefer 'using ns::name' - if you really want to pull a namespace or a name from a namespace, prefer doing so at local scope Doing 'using namespace std' is even worse, because the std namespace is quite huge and there is no portable way to know what headers include what names, so it's really begging for collisions to happen.
But Boost.Math also defines the name 'binomial_distribution' but in the namespace boost::math.
So this implies that it may be necessary to fully qualify boost::math::binomial_distribution at all uses. Ugh!
It's not the end of the world, and actually quite recommended. If boost::math is too long for you, you can alias it to bm for example. In particular, ADL is extremely dangerous, so unless you want the lookup to depend on ADL, you should qualify.
Solution are:
1 Always fully qualify names like "boost:math::binomial_distribution<> my_bd;' This is hideously verbose.
2 Use " std::cout;" etc (instead of "using namespace std;" and "cout<<..." , but it gets tediously verbose.
Come on, it's not that verbose, and you need to do that in headers anyway. 'std::' is pretty short too, and it allows to quickly tell where a name comes from.
participants (2)
-
Mathias Gaunard
-
Paul A. Bristow