Is there a way to "shrink a namespace"?
e.g.
std::chrono::milliseconds to std::milliseconds by the namespace alone?
i.e.
namespace std = std::chrono
(please disregard the fact that this is modifying std. this is just an example I think everyone can understand)
Add your own alias to std::chrono, external to std:
namespace chrono = std::chrono;
And then use chrono::milliseconds.
It's possible to collapse layers of namespaces by adding an internal namespace alias. The standard library does this:
namespace std {
namespace ranges::views { /* views stuff */ }
namespace views = ranges::views;
}
So that std::ranges::views::filter can also be accesses as std::views::filter.
But that doesn't help here because milliseconds is a type, not a namespace. The only way to collapse the contents of a namespace is with a using-directive (or equivalently, a whole lot of using-declarations):
namespace std {
namespace chrono { /* chrono things */ }
using namespace chrono;
}
Which isn't really a good idea because it could just break name lookup for things - especially if anything in std::chrono is named the same as something in std. This also completely defeats the purpose of having the nested namespace to begin with.
So the equivalent to the inner namespace alias would just be the outer namespace alias:
namespace std {
namespace chrono { /* chrono things */ }
}
namespace chrono = std::chrono;
And now you write chrono::milliseconds instead of std::chrono::milliseconds, without having to break anything in any of those namespaces.
Alternatively, if you really want to just shove everything into the same namespace, do it into a different one:
namespace all {
using namespace std;
using namespace std::chrono;
}
Although, as I said, questionable.
If you have a namespace with some deeply nested name that you want to shorten (and it's a namespace you are allowed to modify). e.g:
namespace my {
namespace deeply {
namespace nested {
namespace ns {
// ...
}}}}
you can simplify it with a namespace alias:
namespace my {
namespace easy = deeply::nested::ns;
}
Is there a way to "shrink a namespace"?
You can give namespace an alias, or you can have using namespace declarations.
e.g.
std::chrono::milliseconds to std::milliseconds
Something like that is possible, but not for the std namespace because you may not put such declarations there.
But this is possible for example:
namespace my {
using namespace std::chrono;
}
and this:
namespace my_chrono = std::chrono;
Related
In TOTW 153 it is claimed that using namespace in function scope can leak in the global scope,
in other words they claim this is:
namespace totw {
namespace example {
namespace {
TEST(MyTest, UsesUsingDirectives) {
using namespace ::testing;
Sequence seq; // ::testing::Sequence
WallTimer timer; // ::WallTimer
}
} // namespace
} // namespace example
} // namespace totw
roughly equivalent to:
using ::testing::Expectation;
using ::testing::Sequence;
using ::testing::UnorderedElementsAre;
...
// many, many more symbols are injected into the global namespace
namespace totw {
namespace example {
namespace {
TEST(MyTest, UsesUsingDirectives) {
Sequence seq; // ::testing::Sequence
WallTimer timer; // ::WallTimer
...
}
} // namespace
} // namespace example
} // namespace totw
So I expected that if I do this it will compile:
#include <gtest/gtest.h>
#include <gmock/gmock.h>
namespace totw {
namespace example {
namespace {
TEST(MyTest, UsesUsingDirectives) {
using namespace ::testing;
Sequence seq; // ::testing::Sequence
}
} // namespace
} // namespace example
} // namespace totw
Sequence s; //notice no testing::
It does not. So I wonder if I am wrong in replicating the example, or is the TOTW153 example misleading?
My best guess is that their example is "wrong" in a sense that what they claim is roughly equivalent is not really equivalent in a sense I would assume it is.
You are correct that the "transpiled" code could lead one to think that your last snippet should work. But that's not what they meant.
The using ::testing::Expectation etc. are added to the global namespace from the perspective of the TEST scope. In other words, the transpiled code is effectively identical to the original only within the TEST scope. Outside of that scope there is no effect, but the problems they list are still problems (unless you know that neither the TEST scope contents nor the contents of any involved namespaces will ever be changed). In other words, the using introduces potential collisions between all (present and future) symbols in that TEST scope and the symbols (present and future) in all the involved namespaces. Sounds less scary but will still bite you in the long run.
I am trying to use the directive using namespace NS on a specific member but the compiler doesn't seems to understand so.
This is a very simple sample of code :
namespace NS{
int a;
int b;
}
using namespace NS::a;
int main(){
return 0;
}
Clang compiler returns error: expected namespace name at using namespace NS::a;
a is not namespace. So you can just pull contents of namespace in global namespace with using namespace NS, or pull only a in global namespace with using NS::a.
using namespace NS means that NS is a namespace and you want to have direct access to its scope. So instead of NS::a you can write a directly.
While
using namespace NS::a means that NS is a namespace including another namespace a and you want to have access to variables defined in scope of namespace a !!!
I'm wondering if there's something like a file-specific namespace in C++. Something like the following:
namespace thisFile
{
// whatever code
};
using namespace thisFile;
where thisFile might get translated to some unique thing, such as:
namespace FAJIW0E0RTI43LNAFWENA
{
// whatever code
};
using namespace FAJIW0E0RTI43LNAFWENA;
or perhaps there is an alternative convenient way to accomplish the same thing (i.e. without manually specifying a unique namespace).
Use anonymous namespace:
namespace {
...
}
I'm writing a simple stopwatch template using <chrono>. Since these functions are in std::chrono, it would be convenient to write using namespace std::chrono to avoid bloating up my code lines. But since it's a template, the std::chrono would then be visible in all files which include the template.
What should I do in this situation? Do I have to pick one of the options, or is there a way to avoid the problems of both options?
You can use a namespace alias in you code:
namespace bc = boost::chrono;
and use
bc::duration d;
You can put this alias inside the functions you need boost::chrono so they do not contaminate other code.
template<T>
class foo {
void bar() {
namespace bc = boost::chrono;
bc::duration d;
}
// namespace alias bc is no longer in scope.
}
Alternatively, you can put the using namespace inside the scope of your template/function, however, I think this will reduce readability and will possibly cause conflicts between the boost and C++11 std namespaces.
template<T>
class foo {
void bar() {
using namespace boost::chrono;
duration d;
}
// using namespace boost::chrono is no longer in scope.
}
A recent thread on SO triggerred this.
An anonymous namespace is considered to be equivalent to
namespace unique { /* empty body */ }
using namespace unique;
namespace unique { namespace-body }
I fail to recollect the exact reason as to why it is not equivalent to
namespace unique { namespace-body }
using namespace unique;
Also tried searching (including google) but in vain. Please share any information you have in this regards.
The specification that exists now was introduced in 1995 in N0783 to correct for a corner case. To quote that paper (page 9):
The WP defines the semantics of an unnamed namespace as being equivalent to:
namespace UNIQUE {
// namespace body
}
using namespace UNIQUE;
This is incorrect because it makes the code in an unnamed namespace dependent on
whether the code is in an original namespace or a namespace extension.
namespace {} // If you remove this line, the
// use of ::f below is invalid
namespace {
void f()
{
using ::f;
}
}
The WP should be changed to define an unnamed namespace as being equivalent to:
namespace UNIQUE {}
using namespace UNIQUE;
namespace UNIQUE {
// namespace body
}