1

There are some literal operators in the std::literals namespace with their corresponding header such as operator""s, operator""sv etc.

I wonder why those operators are not automatically export when including the corresponding header since they cannot conflict with each other or user-defined literals operators which must begin with the underscore and usually users like me want to use them when including the header.

It would be nice that the using std::string_literals::operator""s; already in the <string> header as well as other libraries:

#include <string> // automatically export the literal operators
#include <chrono> // automatically export the literal operators
int main() {
  auto str = "hello world"s;
  auto sec = 10s;
}

I can't see any harm with it. Why does Committee not like this? Is there some issue with it or this is a bad practice?

康桓瑋
  • 33,481
  • 5
  • 40
  • 90
  • What do you mean by "export" here? – Nicol Bolas Jan 24 '21 at 17:01
  • 2
    @Evg: As he pointed out, your literals *can't* conflict, since non-standard-library literals must start with `_`. – Nicol Bolas Jan 24 '21 at 17:02
  • Most likely to ensure that the committee could introduce literals in the future for other namespaces in the std without the risk of conflicts. – t.niese Jan 24 '21 at 17:08
  • @Nicol Bolas. It's that I can use `operator""s` without `using std::string_literals::operator""s;` in my code. – 康桓瑋 Jan 24 '21 at 17:10
  • 2
    E.g. `10m` would currently be 10 minutes, but if they would decide to add a measurement namespace with meters, they either would need to choose a different symbol then `m` if this should also be default exported, or it would become inconsistent, why those literals require a `using` and the others don't. – t.niese Jan 24 '21 at 17:19
  • @t.niese: that's why we should use feet/inch as unit measure and get rid of metric system ;-) – Jarod42 Jan 24 '21 at 22:07
  • @t.niese. Although I think the better way is to choose a different symbol such as `mt`, you are right. – 康桓瑋 Jan 25 '21 at 02:41
  • @康桓瑋 you have commonly used symbols for units that you normally want to stick with. In science `mt` would is millitonne (or kilogram). Anyhow, this was just an example, the point is, you don't know what kind of literals you might need in the future, and to avoid conflicts or the need to choose uncommon symbols you don't expose them automatically to the global scope. – t.niese Jan 25 '21 at 07:17
  • @t.niese. Thanks for pointing this out. But the interesting part is that even there are two `operator""m` with the same function signature in a different namespace such as `std::chrono_literals` and imaged `std::measurement_literals`, we still can't use them in the same block scope at the same time whatever them automatically exposed to the global scope or not. – 康桓瑋 Jan 25 '21 at 07:25
  • @康桓瑋 While it is true that you can’t refer to literals using a namespace right now or to alias them, having them in a namespace will allow to do that in future if the need for this is there. On the other hand it is way harder to solve such occurring conflicts later if it would be done in the way you suggest in the question. – t.niese Jan 25 '21 at 10:14
  • @t.niese Actually, the standard uses `operator""min`. But I see your point. – L. F. Feb 03 '21 at 09:16

1 Answers1

3

In C++, a using declaration cannot be undone. Once it's there, every piece of code that follows it (within its scope) will have its name lookup rules affected by that directive. A global using statement is therefore somewhat dangerous. It is even more dangerous in a header, as this will inherently affect the behavior of every file that includes that header (including any headers that get included after that header).

As such, C++ headers do not drop names to the global namespace (except for C standard library names and macros which cannot be namespaced). But UDLs can only be used if they can be accessed without namespace scopes. Therefore, the standard idiom for exposing UDLs is to stick if you want to use literals in some piece of local code, the correct idiom to use is to write the using declaration yourself. And you want these in places that have using scopes like function definitions, not globally or within a namespace scope.

In a codebase that uses C++20 modules, it's much easier to deal with these things, as importing a module will only leak a using directive if you explicitly chose to export it from that module. So globally declaring such a directive in a module won't necessarily corrupt any code that includes that module.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
  • Very appreciate your reply. But in this case, `using std::string_literals::operator""s` is not the dangerous case since it can not expose other literal operators in namespace `std::literals` and there only **one** function in namespace `std::string_literals` which is `operator""s`. Upvote anyway. – 康桓瑋 Jan 25 '21 at 01:20
  • @康桓瑋: C++17 adds `operator""sv` for string_view, and though that's in a different header, it's in the same namespace. Later standards may add more. And it's not a question of "dangerous"; it's a question of polluting the global namespace. That should only be done if you *want* it to happen, not just because you #included `` or any number of headers that themselves include ``. – Nicol Bolas Jan 25 '21 at 02:17
  • Noticed that `operator""s` and `operator""sv` are **not** in the same namespace. Polluting the global namespace is always a bad idea though. Maybe I will write a proposal about this in the future. And still thanks for your response. – 康桓瑋 Jan 25 '21 at 02:37