Cppcoreguidelines: consider using std:: prefix

Created on 15 Nov 2015  Ā·  21Comments  Ā·  Source: isocpp/CppCoreGuidelines

For example in P.1

auto p = find(v, val);

If we ever get an a library with ranges then presumably this becomes even more important, as there could be a std2:find.

open

Most helpful comment

"using namespace X;" changes things like ADL behavior in ways that "using std::vector;" does not. That is, a using declaration for every symbol you use is not the same as a using directive. (I've got a compelling set of examples on that somewhere in my archives that I'm not finding just now, hmph.)

For maintainability, in our experience, the preferences are either:

  • write out std::blah, always
  • write out std::blah in .h files, add a using declaration for each blah you care about in your .cpp file

(I'm actually surprised to see nothing about "Don't pollute the global namespace" in the guidelines as of yet.)

All 21 comments

More importantly, leaving the std:: off of examples sort of implicitly endorses code where people have added "using namespace std;" which we've found to be a huge no-no.

I'm willing to go through and add all the necessary "std::" bits if you give me the go-ahead.

Just to make sure we’re talking about the same thing:

Yes, ā€œusing namespaceā€ should not be used before someone else’s code, namely in a header or in a .cpp before an #include.

However, ā€œusing namespaceā€ is perfectly fine and should be encouraged otherwise. Right?

"using namespace X;" changes things like ADL behavior in ways that "using std::vector;" does not. That is, a using declaration for every symbol you use is not the same as a using directive. (I've got a compelling set of examples on that somewhere in my archives that I'm not finding just now, hmph.)

For maintainability, in our experience, the preferences are either:

  • write out std::blah, always
  • write out std::blah in .h files, add a using declaration for each blah you care about in your .cpp file

(I'm actually surprised to see nothing about "Don't pollute the global namespace" in the guidelines as of yet.)

tituswinters, yeah that is even more important. Probably worth opening a separate issue about that.

To be pedantic, leaving "std::" off "find(v, val)" doesn't in itself endorse any using - boost.range users actually rely on ADL fairly often. But all those "string", "vector", and "cin" certainly do look naked.

Google style guide forbids using namespace foo.

https://google.github.io/styleguide/cppguide.html#Namespaces

I'm in two minds about the issue, though.

I've worked at places which used 'using namespace ...' everywhere. I've
worked at places where they had heavily nested namespaces and aliased them
to acronyms.

My personal rule of thumb is if it comes from the stl then prefix it, if
not use the local naming convention.

GR

Sent from my Nexus 5.
On 20 Nov 2015 8:46 a.m., "blakehawkins" [email protected] wrote:

Google style guide forbids using namespace foo.

https://google.github.io/styleguide/cppguide.html#Namespaces

I'm in two minds about the issue, though.

—
Reply to this email directly or view it on GitHub
https://github.com/isocpp/CppCoreGuidelines/issues/391#issuecomment-158327069
.

Another point: Any open source library that has bad hygiene in this area in their headers is likely to have (or cause) build problems when being imported into an existing codebase.

Another way to approach it: specifically add a rule saying what is recommended (see my previous for my suggestions) and an editorial note there saying "The examples in this document may elide the std:: for brevity." But certainly something ought to be said.

@tituswinters
I like that suggestion.
We don't want to rule out the namespace composition technique, which often means a using directive at a named scope in a header file. The case that almost always causes grief is a using directive at a global scope in a header file.

Note that an inline namespace implicitly requires a using directive, and is usually meaningful only in a named scope.

Myself, I've only found namespace composition useful on a temporary basis (fixing poorly named namespaces when you can't do the rename in one giant commit, or moving things from one namespace to another). But I certainly wouldn't want to prevent those sorts of uses. Or even _intentional_ import of the contents of one namespace into another. Just don't pollute the global (and on average, don't muck with std).

I think the STL guidelines should mention something about using namespace. This SO discussion has a lot of interesting insight as well - http://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice

And it also happens to be the first result when googling "is using namespace good"

Oh, ping on this.

@tituswinters
Update soon -- holiday happened :-)

Yep. I'm doing an editorial pass on the later sections and couldn't remember what was decided here wrt. std::, that's all. No rush.

I'm a big fan of explicitly typing out namespaces. When reading code, I don't like having to go search for a 'using' directive in order to figure out if that is a custom find() function, or std::find. (Of course many IDEs can help locate which find() it is.)

The difference is often between writing code and reading or _debugging_ code. When debugging, you need to know if you should suspect the bug is in find() or not, and whether you should look into it. (And if it is std::find() the bug is probably elsewhere.)

I am of the opinion that _sometimes_ using namespace ... is useful, even in header files (as long as its not in the global _namespace_) for limited numbers of symbols that rightfully can be considered as being a part of another _namespace_. But truly massive _namespaces_ like std:: don't fall into this category. Furthermore the sheer extent and character of the symbols they contain always leads to potentially hard to find bugs, even if used in a .cpp file.

So I recommend _always_ prefixing with std:: or other largely populated general purpose _namespaces_ (or using declarations or namespace aliasing) except in very limited, local scopes.

What I might consider a ligitimate use would be for example:

namespace mylib { namespace types {

using size_type = std::size_t;
using integral = std::int32_t;
using real = double;
using clock = std::chrono::steady_clock;
using period = clock::period;
using duration = clock::duration;

}} // mylib::types

// ...

namespace my_project {

using namespace mylib::types; // don't bother redeclaring all those types, just import them

// ...

} // my_project

Another way I use this is to have _namespace_ groups within a larger project namespace so that including the larger namespace still leaves you with group namespace prefixes to keep from polluting your larger codebase.

namespace my_algorithm_library { namespace stl {

template<typename Iter>
Iter algorithm1(Iter a, Iter b)
{
    // ...
}
// etc..
}} // my_algorithm_library::stl

// ...

namespace my_project {

using namespace my_algorithm_library;
// still have to further qualify names here ...

void func(std::vector<int>& v)
{
    auto i = stl::algorithm1(v.begin(), v.end());
    // ...
}

} // my_project

By having the second level of namespace you still need to qualify symbols from the larger namespace you included and any ambiguities there could be fixed using _namespace aliases_.

I think the only time one should use "using namespace foo" is when the
maintainer of foo has access to your source code and would be able to catch
and perhaps fix problems when the maintainer adds a new symbol to the foo
namespace. For example, when the definition and uses of foo are all within
the same project.

On Tue, Mar 15, 2016 at 12:31 PM, Galik [email protected] wrote:

I am of the opinion that _sometimes_ using namespace ... is useful, even
in header files (as long as its not in the global _namespace_) for
limited numbers of symbols that rightfully can be considered as being a
part of another _namespace_. But with truly massive _namespaces_ like
std:: don't fall into this category. Furthermore the sheer extent and
character of the symbols they contain always leads to potentially hard to
find bugs, even if used in a .cpp file.

So I recommend _always_ prefixing with std:: or other large general
purpose _namespaces_ (or using declarations or namespace aliasing) except
in very limited, local scopes.

What I might consider a ligitimate use would be for example:

namespace mylib { namespace types {
using size_type = std::size_t;using integral = std::int32_t;using real = double;using clock = std::chrono::steady_clock;using period = clock::period;using duration = clock::duration;

}} // mylib::types
// ...
namespace my_project {
using namespace mylib::types; // don't bother redeclaring all those types, just import them
// ...

} // my_project

Another way I use this is to have _namespace_ groups within a larger
project namespace so that including the larger namespace still leaves you
with group namespace prefixes to keep from polluting your larger codebase.

namespace my_algorithm_library { namespace stl {
template
Iter algorithm1(Iter a, Iter b)
{
// ...
}// etc..
}} // my_algorithm_library::stl
// ...
namespace my_project {
using namespace my_algorithm_library;// still have to further qualify names here ...
void func(std::vector& v)
{
auto i = stl::algorithm1(v.begin(), v.end());
// ...
}

} // my_project

By having the second level of namespace you still need to qualify symbols
from the larger namespace you included and any ambiguities there could be
fixed using _namespace aliases_.

—
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:

https://github.com/isocpp/CppCoreGuidelines/issues/391#issuecomment-196909258

I am generally in favor of namespace prefixes. However, it is also worth pointing out that there are places where they get in the way rather than aid. Especially, as noted before, with std:: or std::trX:: and so forth. There can be places where the prefix can become redundant and tedious.

In many cases using std:: is redundant. For example, std::string is not more confusing as simply string. Could a library be using their own string type? Sure. Probably they are not. Other situations are also not necessarily confusing. Or at least, not more confusing than they already are. For example find or any other function call. Is it a global function? Is it a member function? Is it inherited from a base class?

It is good to be explicit when the scope is unclear. However, it also important to balance precision with readability.

I asked a couple of questions related to this on #725

hmm, Well for me I never use a namespace globally. However I do use a namespace within functions themselves to help reduce the need to type std:: a lot. And the reason for this is that I am not sure how much problems could happen when I do it globally. in Source Files. In header files it is never ok to use any full namespaces unless they do not have a lot of methods / functions / properties. But even then I reluctantly use namespaces because I never know when it might not only increase compile time, but also assembly size and, as such more assembly instructions that can be avoided otherwise. So, even if I use an namespace. It would be inside of functions to where the actual costs would not be as much of an issue.

Going back to the original topic of whether the std:: prefix should be used in the document's examples or not:

I think it should be added irrespective of the general discussion if using namespace std; is fine in certain cases or not.

  • If nothing else then to point out, when an example is specifically referring to an actual standard library identifier that you can use out of the box vs some ad-hoc function / type / concept vs an overload set relying on ADL.

  • Also, truth in advertising: Imho the examples promoting "good" style should not imply a brevity that many won't actually get in practice (if they are working in headers or their coding guideline forbidds using namespace std; anywhere).

    auto p = find(begin(v), end(v), val);

    vs

    auto p = std::find(std::begin(v), std::end(v), val);

    or for the generic case:

    using std::begin;
    using std::end;
    auto p = std::find(begin(v), end(v), val);

    (still much shorter than the hand-written version)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Artikash picture Artikash  Ā·  5Comments

HowardHinnant picture HowardHinnant  Ā·  3Comments

jeffreylindsey picture jeffreylindsey  Ā·  5Comments

beinhaerter picture beinhaerter  Ā·  5Comments

franzhollerer picture franzhollerer  Ā·  6Comments