|
Boost : |
Subject: [boost] https://svn.boost.org/trac/boost/ticket/4515 Nasty naming conundrum? (Or does C++ need a 'not using ...; ' statement?)
From: Paul A. Bristow (pbristow_at_[hidden])
Date: 2010-08-31 04:55:16
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_at_[hidden]
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk