15

I have defined the following user-defined literal in MyLiteral.h:

namespace my_literals {
    constexpr uint64_t operator"" _nanoseconds(unsigned long long int value) {
        return value*1000;
    }
}

Now I could use the operator in another header SomeComponent.h:

using namespace my_literals;
namespace foo {
    constexpr uint64_t timeout = 10_nanoseconds;
}

However, I don't want to pollute the scope by using namespace my_literals, because this would provide the literal definition to all *.cpp files which include SomeComponent.h.

How can I avoid this? constexpr uint64_t timeout = my_literals::10_nanoseconds; gives expected unqualified-id before numeric constant in g++.

Rakete1111
  • 47,013
  • 16
  • 123
  • 162
Alexander
  • 1,068
  • 6
  • 22
  • Sorry, I reopened because the duplicate answer did not have the constraint of being in a header file, but it turns out the solution is the same either way. I reclosed it as a duplicate. – Emile Cormier Sep 13 '20 at 19:12
  • I don't think this is a duplicate at all. It is a more constrained case of the alleged duplicate, and requires different solutions. The accepted answer (and only one at this point) in the other question uses a scope and a `using namespace` declaration that cannot be used in a header. – Alejandro Exojo Feb 17 '22 at 06:55

3 Answers3

15

In C++17, with constexpr lambda, you may do:

namespace foo {
    constexpr uint64_t timeout = []{ using namespace my_literals; return 10_nanoseconds; }();
}

as alternative to (C++11 and higher):

namespace foo {
    constexpr uint64_t timeout = my_literals::operator""_nanoseconds(10);
}

or

namespace foo {

    namespace detail
    {
        using namespace my_literals;
        constexpr uint64_t timeout = 10_nanoseconds;
    }
    using detail::timeout;
}
Jarod42
  • 203,559
  • 14
  • 181
  • 302
8

You can get around this by calling the operator explicitly:

namespace foo {
    constexpr uint64_t timeout = my_literals::operator""_nanoseconds(10);
}
DeiDei
  • 10,205
  • 6
  • 55
  • 80
  • 13
    Extremely ugly :) – kreuzerkrieg Jun 20 '18 at 08:00
  • @kreuzerkrieg No doubt. It's fine for library code though. – DeiDei Jun 20 '18 at 08:01
  • 1
    I can confirm this works and comprises my intention. However, it is obviously ugly and no longer an intuitive literal. – Alexander Jun 20 '18 at 08:01
  • @Alexander By the way, why don't you use `std::chrono` utilities? – DeiDei Jun 20 '18 at 08:03
  • 1) I am on a constrained embedded system which tightly integrates with an RTOS and its own definition of time. 2) I was unaware of `std::chrono` and will take a look. Thanks for the suggestion. – Alexander Jun 20 '18 at 08:10
  • namespace foo { using namespace my_literals; constexpr uint64_t timeout = 10_nanoseconds; } this should also work - easier to read. – Tunichtgut Jun 20 '18 at 08:50
  • @Tunichtgut: you miss OP's point, as then, after `using namespace foo;` you can do `10_nanosecond`. – Jarod42 Jun 20 '18 at 09:00
  • In this case why even use literals? There are many old pre - c++11 methods which would look more elegant than this. – vsz Jun 20 '18 at 11:36
  • 1
    @vsz I assumed this was library code and the `using namespace` is not supposed to be leaked to the user. – DeiDei Jun 20 '18 at 11:40
0

You could put the using declaration inside the namespace (if you don't mind having foo::operator""_nanoseconds available):

namespace foo {
    using namespace my_literals;
    constexpr uint64_t timeout = 10_nanoseconds;
}
Solomon Ucko
  • 5,724
  • 3
  • 24
  • 45