What is the benefit of std::literals::.. being inline namespaces? - c++

In the C++-Standard (eg. N4594) there are two definitions for operator""s:
One for std::chrono::seconds :
namespace std {
...
inline namespace literals {
inline namespace chrono_literals {
// 20.15.5.8, suffixes for duration literals
constexpr chrono::seconds operator "" s(unsigned long long);
and one for std::string :
namespace std {
....
inline namespace literals {
inline namespace string_literals {
// 21.3.5, suffix for basic_string literals:
string operator "" s(const char* str, size_t len);
I wonder what is gained from those namespaces (and all the other namespaces inside std::literals), if they are inline.
I thought they were inside separate namespaces so they do not conflict with each other. But when they are inline, this motivation is undone, right? Edit: Because Bjarne explains the main motivation is "library versioning", but this does not fit here.
I can see that the overloads for "Seconds" and "String" are distinct and therefor do not conflict. But would they conflict if the overloads were the same? Or does take the (inline?) namespace prevents that somehow?
Therefore, what is gained from them being in an inline namespace at all?
How, as #Columbo points out below, are overloading across inline namespaces resolved, and do they clash?

The user-defined literal s does not "clash" between seconds and string, even if they are both in scope, because they overload like any other pair of functions, on their different argument lists:
string operator "" s(const char* str, size_t len);
seconds operator "" s(unsigned long long sec);
This is evidenced by running this test:
void test1()
{
using namespace std;
auto str = "text"s;
auto sec = 1s;
}
With using namespace std, both suffixes are in scope, and yet do not conflict with each other.
So why the inline namespace dance?
The rationale is to allow the programmer to expose as few std-defined names as desired. In the test above, I've "imported" the entire std library into test, or at least as much as has been #included.
test1() would not have worked had namespace literals not been inline.
Here is a more restricted way to use the literals, without importing the entire std:
void test2()
{
using namespace std::literals;
auto str = "text"s;
auto sec = 1s;
string str2; // error, string not declared.
}
This brings in all std-defined literals, but not (for example) std::string.
test2() would not work if namespace string_literals was not inline and namespace chrono_literals was not inline.
You can also choose to just expose the string literals, and not the chrono literals:
void test3()
{
using namespace std::string_literals;
auto str = "text"s;
auto sec = 1s; // error
}
Or just the chrono literals and not the string literals:
void test4()
{
using namespace std::chrono_literals;
auto str = "text"s; // error
auto sec = 1s;
}
Finally there is a way to expose all of the chrono names and the chrono_literals:
void test5()
{
using namespace std::chrono;
auto str = "text"s; // error
auto sec = 1s;
}
test5() requires this bit of magic:
namespace chrono { // hoist the literals into namespace std::chrono
using namespace literals::chrono_literals;
}
In summary, the inline namespaces are a tool to make all of these options available to the developer.
Update
The OP asks some good followup questions below. They are (hopefully) addressed in this update.
Is using namespace std not a good idea?
It depends. A using namespace is never a good idea at global scope in a header that is meant to be part of a general purpose library. You don't want to force a bunch of identifiers into your user's global namespace. That namespace belongs to your user.
A global scope using namespace can be ok in a header if the header only exists for the application you are writing, and if it is ok with you that you have all of those identifiers available for everything that includes that header. But the more identifiers you dump into your global scope, the more likely it is that they will conflict with something. using namespace std; brings in a bunch of identifiers, and will bring in even more with each new release of the standard. So I don't recommend using namespace std; at global scope in a header even for your own application.
However I could see using namespace std::literals or using namespace std::chrono_literals at global scope in a header, but only for an application header, not a library header.
I like to use using directives at function scope as then the import of identifiers is limited to the scope of the function. With such a limit, if a conflict does arise, it is much easier to fix. And it is less likely to happen in the first place.
std-defined literals will probably never conflict with one another (they do not today). But you never know...
std-defined literals will never conflict with user-defined literals because std-defined literals will never start with _, and user-defined literals have to start with _.
Also, for library developers, is it necessary (or good practice) to have no conflicting overloads inside several inline namespaces of a large library?
This is a really good question, and I posit that the jury is still out on this one. However I just happen to be developing a library that purposefully has conflicting user-defined literals in different inline namespaces!
https://github.com/HowardHinnant/date
#include "date.h"
#include "julian.h"
#include <iostream>
int
main()
{
using namespace date::literals;
using namespace julian::literals;
auto ymd = 2017_y/jan/10;
auto jymd = julian::year_month_day{ymd};
std::cout << ymd << '\n';
std::cout << jymd << '\n';
}
The above code fails to compile with this error message:
test.cpp:10:20: error: call to 'operator""_y' is ambiguous
auto ymd = 2017_y/jan/10;
^
../date/date.h:1637:1: note: candidate function
operator "" _y(unsigned long long y) NOEXCEPT
^
../date/julian.h:1344:1: note: candidate function
operator "" _y(unsigned long long y) NOEXCEPT
^
The _y literal is used to create year in this library. And this library has both a Gregorian calendar (in "date.h") and a Julian calendar (in "julian.h"). Each of these calendars has a year class: (date::year and julian::year). They are different types because the Gregorian year is not the same thing as a Julian year. But it is still convenient to name them both year and to give them both a _y literal.
If I remove the using namespace julian::literals; from the code above then it compiles and outputs:
2017-01-10
2016-12-28
which is a demonstration that 2016-12-28 Julian is the same day as 2017-01-10 Gregorian. And this is also a graphic demonstration that the same day can have different years in different calendars.
Only time will tell if my use of conflicting _ys will be problematic. To date it hasn't been. However not many people have used this library with non-Gregorian calendars.

Related

Is it proper to use qualified lookup with no namespace on the left of the scoping operator (::name) in general code?

This sample code from cppreference.com:
#include <iostream>
int main() {
struct std{};
std::cout << "fail\n"; // Error: unqualified lookup for 'std' finds the struct
::std::cout << "ok\n"; // OK: ::std finds the namespace std
}
shows how ::name (no namespace on the left side of the scoping operator) refers to a name unambiguously.
An analogy can be made with filesystems. In filesystems, to refer to a file unambiguously, it is standard to refer to it by its absolute path, such as /home/username/hello.txt with a leftmost /.
On the other hand, it seems to be the established coding style in C++ to never refer to a name unambiguously, i.e., the scoping operator with a right argument only is rare. But since a fully unambigious lookup exists, it is surprising that ::std::cout isn't the standard coding style. It is always std::cout (no leftmost scoping operator, resulting in unqualified lookup of the leftmost namespace), which is error-prone, as the sample code shows.
Summary of the question: What serious reasons are there to support the style std::cout (unqualified lookup of the leftmost namespace) over ::std::cout (qualified lookup of everything)?
What serious reasons are there to support the style std::cout (unqualified lookup of the leftmost namespace) over ::std::cout (qualified lookup of everything)?
It's already hard enough to persuade people to write std::, let alone ::std::. The former is only "error-prone" if you have no naming standards. Much simpler is to forbid naming anything std.
std should be a reserved identifier, but for compatibility with C.
Argument-dependent lookup only works for unqualified function calls, which excludes using the nested-name-specifier ​:: if wanting to leverage ADL; [basic.lookup.argdep]/1
When the postfix-expression in a function call is an unqualified-id,
Using qualified names with a leading :: also forces developers to include possibly long-winded top-level->and->down namespace names in cases where these could otherwise be omitted, leading to verbosity that could give incentive for developers to create(/refactor) namespaces with (/into using) abbreviated names that are
more likely to collide with namespaces of other projects, and
more difficult to understand the meaning of for a future reader.
E.g., the following
namespace my_projects_well_named_top_level_namespace {
namespace my_core_utils {
void f() {};
}
namespace my_module_a {
void g() {
// Ok.
my_core_utils::f();
// Refactorer: This is too long.. let's rename the top-level.
::my_projects_well_named_top_level_namespace::my_core_utils::f();
}
} // namespace my_module_a
} // namespace my_projects_well_named_top_level_namespace
may, for the entirely wrong reasons (long and/or nested namespace names can be addressed locally within a TU using namespace aliases; see e.g. TotW #119), be re-factored into
namespace mp {
namespace my_core_utils {
void f() {};
}
namespace my_module_a {
void g() {
// Refactorer: Ok, nice!
::mp::my_core_utils::f();
}
} // namespace my_module_a
} // namespace mp
// Sometime later: Ehm, what is mp?
which, with its abbreviated name, may open up for collision (even silent ones) with 3rd party libraries which have happen to have chosen the same brilliantly abbreviated top-level namespace:
// ------------------- 3rdparty lib
namespace mp {
void f(int);
} // namespace mp
// ------------------- your project
namespace mp {
// We are now in the same declarative region
// as that of the 3rd party library.
struct S {
int x;
operator int() const { return x; }
};
namespace my_module_a {
void f(S) {}
} // namespace my_module_a
namespace my_module_b {
void g() {
// unqualified lookup _will not_ find my_module_a::f(S).
// ADL finds mp::foo(int) from the 3rd party lib
f(S{}); // #1
}
} // namespace my_module_b
} // namespace mp
(where of course the author of #1 has not followed the original refactorers intentional rule of using fully qualified names with leading nested-name-specifier).

Difference between sibling namespaces in nested vs global context

I have some C++ libraries that are written using nested namespaces. These libraries use many mathematical functions that, for readability, are better off read without explicitly specifying namespaces. Right now, a simplified version of the code would look like this.
namespace Base::Sibling1 {
float cos(float x) { return cosf(x); }
};
namespace Base::Sibling2 {
using namespace Sibling1;
float f(float x) { return cos(x); }
};
We wanted to move to use flatter namespaces mostly to make it easier to extend the library with sibling code. We had hoped that a simple change like this would work:
namespace Sibling1 {
float cos(float x) { return cosf(x); }
};
namespace Sibling2 {
using namespace Sibling1;
float f(float x) { return cos(x); }
};
Instead this fails now since Sibling2::f() calls cos(x) that is now ambiguous.
I have two questions
why is it ambiguous now and not int the first version?
is it possible to obtain the behavior we had before without listing all functions explicitly using using Sibling1::cos?
The ambiguity is due to how using directives work.
[namespace.udir] (emphasis mine)
2 A using-directive specifies that the names in the nominated
namespace can be used in the scope in which the using-directive
appears after the using-directive. During unqualified name lookup
([basic.lookup.unqual]), the names appear as if they were declared in
the nearest enclosing namespace which contains both the
using-directive and the nominated namespace. [ Note: In this context,
“contains” means “contains directly or indirectly”. — end note ]
3 A using-directive does not add any members to the declarative
region in which it appears. [ Example:
namespace A {
int i;
namespace B {
namespace C {
int i;
}
using namespace A::B::C;
void f1() {
i = 5; // OK, C​::​i visible in B and hides A​::​i
}
}
namespace D {
using namespace B;
using namespace C;
void f2() {
i = 5; // ambiguous, B​::​C​::​i or A​::​i?
}
}
void f3() {
i = 5; // uses A​::​i
}
}
void f4() {
i = 5; // error: neither i is visible
}
— end example ]
So given your structure of namespaces, according to bit I made bold in paragraph 2, when you write
using namespace Sibling1;
It kinda translates to this
namespace /* Enclosing */ {
using Sibling1::cos;
namespace Sibling2 {
float f(float x) { return cos(x); }
};
}
The namespace I marked as enclosing is either Base or the global namespace. The "kinda" bit (according to paragraph 3) is that it's not an actual declaration being added. I.e. if something named cos already exists in /* Enclosing */, it's not a re-declaration. This is by design, because using directives can potentially bring a lot of names in, and so it shouldn't cause an error when the names they bring are not actually used.
In your case however, the name brought in is used.
When /* Enclosing */ is Base, it matches only one declaration, the one in Sibling1, as-if it was declared in Base.
When /* Enclosing */ is the global namespace, it matches the actual declaration there too, presumably the one brought in by math.h (you seem to be using that). So you get an ambiguity (the name refers to two potential entities).
So on the whole, compilers that reject this code are behaving as expected. While I understand your plight, I don't think there's really a problem for you to solve here. If client code finds Base::Sibling1::cos too verbose, it itself can employ a using directive of the form using namespace Base;. Or using a namespace alias to shorten things namespace sib1 = Base::Sibling1;.
The problem cannot be reproduced as you describe it. Moreover, there is no reason that the flattening alone introduces ambiguities, if you use expose in the siblings the same names you introduced in Base. So, the root cause is probably in some parts of the code you are not showing.
The second version does not define cosf(), so you probably are using some namespace. If in that namespae there is also a cos() you create an ambiguity between the two overloads. I could reproduce this by using namespace std:
#include <iostream>
#include <cmath>
using namespace std;
namespace Sibling1 {
float cos(float x) { return cosf(x); }
}
namespace Sibling2 {
using namespace Sibling1;
float f(float x) { return cos(x); }
}
Online demo: the compilation error indicates which are the candidates behind the ambiguity. If you now comment the using namespace out, the ambiguity goes away, and the code compiles. Online proof.
Namespaces are meant to avoid naming conflicts and keep control of ambiguities:
Creating a namespace and systematically using namespace everywhere defeats the whole purpose.
On the other side, long using lists are painful to maintain, especially if you have to repeat them in several sibling namespaces. This is probably why the Base and the nesting were created in the first place.
In the first version, you do not show what's in Base. It is possible that some more tailored using clauses are used therein instead of full namespaces: if selectively injecting the really required functions in the Base namespace, they are made available within the siblings avoiding ambiguity that can be introduced by injecting the name of unnecessary functions.

so I decided to not use namespace anymore, but now when should I add std:: or cv::?

I recently started using c++ and opencv for image processing. since the beginning almost every sample code had using namespace std; in the header. after reading about it I saw that it is recommended not to use namespace since it can lead to problems when two libraries have the same function name.
so I changed it and used cv:: and std:: whenever I got an error but still there were functions from opencv that had no error I assume this is because there's only one function with that name. but should I add the identifier for every function even if this doesn't lead to an error?
for example
cv::Mat antif;
idft(complexI, antif);
split(antif, planes);
magnitude(planes[0], planes[1], antif);
normalize(antif, antif, 0, 1, cv::NORM_MINMAX);
I'm measuring the phase difference between two images using Fourier transform.
I had to add cv:: when making the variable antif. but no error popped up for any of the following functions included in opencv.
is this because there is only one instance of this questions or should I add cv:: just to get used to doing so?
ADL has been mentioned in another answer.
Here's how it works:
In the example below, notice that the function show has been defined in namespaces Foo and Bar.
ADL allows the compiler to look in all namespaces mentioned in the argument list.
x1 is a Foo::X so in the first call to show() the following namespaces may be checked:
Foo
:: (the global namespace)
any namespace pulled into Foo with a using namespace
any namespace pulled into the global namespace with a using namespace (which is why we don't use using namespace in the global namespace)
#include <iostream>
namespace Foo
{
struct X{};
void show(X const&)
{
std::cout << "a Foo::X" << std::endl;
}
}
namespace Bar
{
struct X{};
void show(X const&)
{
std::cout << "a Bar::X" << std::endl;
}
}
int main()
{
auto x1 = Foo::X();
auto x2 = Bar::X();
show(x1);
show(x2);
}
expected output:
a Foo::X
a Bar::X
These functions are found by argument-dependent lookup. So, they are in the cv namespace, but the compiler is able to guess this because the type of (at least) one of the arguments is in the cvnamespace.

How can I explicitly refer to an enclosing namespace when an inline namespace exists?

Please consider this code:
#include <iostream>
namespace Foo{
void ool() // Version A
{
std::cout << "Foo::ool" << std::endl;
}
inline namespace Bar{
void ool() // Version B
{
std::cout << "Foo::Bar::ool" << std::endl;
}
}
}
int main()
{
Foo::ool(); // <- error
}
Both Clang and G++ correctly mark Foo::ool as ambiguous. I can call Foo::Bar::ool without problem but is there a way to call the version A without changing its declaration?
I found people in similar position trying to understand what happens but I did not see a solution for this case.
I am in this situation because I have a project that includes a declaration of std::__1::pair and std::pair, made in different places, with std::__1 being an inline namespace. I need the code to point to the std::pair explicitly. Is there a solution for that?
I don't think that is possible; from cppreference:
Qualified name lookup that examines the enclosing namespace will include the names from the inline namespaces even if the same name is present in the enclosing namespace.
However, it seems you are not actually in the situation you describe, as you say that the two definitions are pulled from different files. Thus you "bookmark" the more external definition in order to be able to call it when you need it:
#include <iostream>
// Equivalent of first include
namespace Foo{
void ool() // Version A
{
std::cout << "Foo::ool" << std::endl;
}
}
const auto& foo_ool = Foo::ool;
// Equivalent of second include
namespace Foo{
inline namespace Bar{
void ool() // Version B
{
std::cout << "Foo::Bar::ool" << std::endl;
}
}
}
int main()
{
foo_ool(); // Works
}
If the thing you want to bookmark is a type, a simple using directive should suffice. The equivalent code for you would look like:
#include <my_first_include>
// bookmark code
#include <my_second_include>
// rest of the code
You cannot unambiguously refer to the symbol defined in the enclosing namespace once the inline namespace has been seen.
In particular for you case, the qualified lookup in main is rightfully flagged as being ambiguous (as you said yourself). See the last point on cppreference:
Qualified name lookup that examines the enclosing namespace will include the names from the inline namespaces even if the same name is present in the enclosing namespace.
Yet, has other pointed out in comments, you are probably facing a problem of configuration in your toolchain invocation when you try to use std::pair.
To fix you problem, you need to make sure the compiler is invoked to compile C++11 code, which would be with the flag:
-std=c++11 or -std=c++0x depending on your version of Clang/GCC
To give further context:
The inline namespace is a C++11 feature, mainly introduced to allow for symbol versioning in libraries. A C++ standard library implementation could then define different versions of symbols in nested namespaces (with non-standard names), and depending on the requested library version when compiling, the toolchain defines one of those nested namespaces as inline. It seems you are using a c++11 version of the library (since it defines some symbols, in particular pair, in the inline namespace _1), so having symbols in an inline namespace in actually what you want.
I don't think you can refer ool ambiguously when an inline namespace do have a method with same name ool .
But You can try this;
#include <iostream>
namespace Foo{
inline namespace A {
void ool() // Version A
{
std::cout << "Foo::ool" << std::endl;
}
}
namespace Bar{
void ool() // Version B
{
std::cout << "Foo::Bar::ool" << std::endl;
}
}
}
int main()
{
Foo::ool(); // no error
}
Wrap methods in namespace Foo in a namespace A then inline namespace A.
Remove inline from Bar.
Now if you make a call Foo::ool(); it will invoke inline A::ool()
Bar::ool can be invoked by Foo::Bar::ool

namespace in c++

what is the use of using declaration type of namespacing over using directive type of namespacing??when to use each one of them?
The declaration type of namespace directive introduces selected named symbols into your code scope (and leaves other symbols from the same namespace inaccessible without the namespace qualifier).
The using type of namespace directive introduces all symbols from the namespace into your code scope - which means you don't necessarily know exactly which symbols were introduced (there could have been undocumented symbols, or symbols left over from previous versions of the library, or ...).
For control, use the declaration type of namespace directive.
For convenience (with risk), use the using type of namespace directive.
Besides the using declaration allowing access to a symbol rather than a namespace, the using declaration also brings the symbol to the scope of the declaration. The using directive only affects lookup.
Jonathan already resumed the differences between using namespace foo; and using foo::Bar; but I think his answer is unfortunately incomplete.
First: using namespace should never appear in a header file. By doing so you might render it impossible to use in combination with other header files because of a symbol clash...
Second: in general, you should try to limit the scope of the symbols as much as possible, you probably already do it while writing code:
for (size_t i = 0; i < 5; ++i)
{
std::string myString = myVec.at(i);
if (myString == "Foo") { std::cout << "Found"; break; }
}
Here it would be useless (and polluting) to have myString declared outside the for loop. In fact, that very advice can be found in a number of books:
From Scott Meyers' Effective C++, Item 26: Postpone variable definitions as long as possible.
From Herb Sutter and Andrei Alexandrescu's C++ Coding Standard, Item 18: Declare variables as locally as possible
There is no reason not to do the same with using declarations.
Third: consider alternatives to using: namespace aliasing and typedef.
// foo.h
class Foo
{
public:
std::vector<std::string> getSynonyms(const std::string& s) const;
private:
typedef std::map< std::string, std::vector<std::string> > synonyms_type;
synonyms_type mSynonyms;
};
// foo.cpp (never in header, at general scope)
namespace fu = boost::fusion;
std::vector<std::string> Foo::getSynonyms(const std::string& s) const
{
synonyms_type::const_iterator it =
std::find(mSynonyms.begin(), mSynonyms.end(), s);
std::vector<std::string> result;
if (it != mSynonyms.end()) { result = it->second; }
return result;
}
What are the advantages ?
namespace aliasing > reduce typing almost as much without injecting the types right in the current scope so without risk
typedef > reduce typing more than using and allow easy change of underlying type too.