3

If we want to use some UDL we need to use the corresponding namespace:

auto foo()
{
   using namespace std::literals::chrono_literals;

   std::chrono::milliseconds interval = 1s;
}

which is all right and well because the introduced namespace is localized to the function.

But I haven't found a solution to use them outside of a function scope (e.g. in-class initializer or function default argument) without polluting the enclosing namespace:

// this is a header

namespace my_ns
{

// I would like to avoid this:
// using namespace std::literals::chrono_literals;

struct Foo
{
   // can't have a using directive at class scope:
   // using namespace std::literals::chrono_literals;


   // I want to do this
   std::chrono::milliseconds interval = 1s;

   // I want to pretty pretty pretty please do this:
   Foo(std::chrono:milliseconds interval = 1s) : interval{interval} {}
};
}

Is there a better way to use UDL here?

bolov
  • 72,283
  • 15
  • 145
  • 224
  • ```// I would like to avoid this: // using namespace std::literals::chrono_literals;``` why? – yuri kilochek Aug 01 '17 at 18:47
  • @yurikilochek because it introduces the literals in a too broad scope. I want them localized to where I use them only. Keep in mind this is a header. – bolov Aug 01 '17 at 18:48
  • So? All literal suffixes not starting with '_' are reserved anyway, so there is no possibility of collision. – yuri kilochek Aug 01 '17 at 18:50
  • 1
    @yurikilochek 1. yes there is: string vs second. 2. this is not about reserved literals only, it should be applied to user literals also. And there you have to expect collisions. And besides, I probably will end up doing that anyway, I just hope for a better and cleaner solution. – bolov Aug 01 '17 at 18:53
  • 1. no, they don't collide, one is for strings other is for numbers, same way overloaded functions do not collide. 2. fair enough. – yuri kilochek Aug 01 '17 at 18:56
  • @bolov - The string and second literals are defined using completely different overloads. ADL is applied here too. They will not conflict, despite using the same suffix. – StoryTeller - Unslander Monica Aug 01 '17 at 18:56
  • @yurikilochek. StoryTeller yes you are correct. I was wrong on that. – bolov Aug 01 '17 at 18:57
  • Don't you prefer to write `std::chrono::milliseconds interval = std::literals::chrono_literals::operator ""s(1ULL)` ? – Jarod42 Aug 01 '17 at 23:20

2 Answers2

2

How about this?

namespace my_ns {
  namespace _ {
    using namespace std::literals::chrono_literals;
    struct Foo {
      std::chrono::milliseconds interval = 1s;

      Foo(std::chrono:milliseconds interval = 1s) : interval{interval} {}
    };
  }

  using Foo = _::Foo;
}
  • even if it works and doesn't mess ADL in an unexpected and spectacular way... it's kind of ugly. The programmer looking over this would not have to say nice things about me :)) – bolov Aug 01 '17 at 18:50
  • Oh I'm fully with you on that! but it _is_ a way of acomplishing what you want. –  Aug 01 '17 at 18:51
  • well I must not forget that my original issue is that I want a clean and nice code. But interesting technical approach. I apreciate it. – bolov Aug 01 '17 at 18:55
  • Just pitching to say it won't harm ADL. ADL looks in the namespace where the *type* is defined. An alias doesn't introduce a new type, so it will look in `my_ns::_`. – StoryTeller - Unslander Monica Aug 01 '17 at 19:00
  • 1
    I think that's @bolov's concern. He's worried that functions defined elsewhere in `my_ns` won't be found by ADL. –  Aug 01 '17 at 19:01
  • @bolov - If you don't like `_` then name it `detail`. I believe that's the convention. – StoryTeller - Unslander Monica Aug 01 '17 at 19:02
  • 1
    @Frank - ADL looks in all containing namespaces, starting at the smallest. If it won't find it in `my_ns::_`, it will look in `my_ns` next. The committee foresaw this long ago. – StoryTeller - Unslander Monica Aug 01 '17 at 19:03
  • @StoryTeller good to know. Thank you. Found a way it can fail. Although it should be pretty rare, it's not silent, and easily fixed anyway. So in the end it doesn't matter :) just trying to think of all the possibilities as an exercise: https://godbolt.org/g/caGXuw – bolov Aug 01 '17 at 19:25
  • @bolov - My second comment to Frank should address *that* eager to help the compiler user. – StoryTeller - Unslander Monica Aug 01 '17 at 19:28
0

You may add a (private) function as work around:

namespace my_ns
{

   struct Foo
    {
       std::chrono::milliseconds interval = one_second();

       Foo(std::chrono::milliseconds interval = one_second()) : interval{interval} {}
    private:
        static std::chrono::seconds one_second() {
            using namespace std::literals::chrono_literals;
            return 1s;
        }
    };
}
Jarod42
  • 203,559
  • 14
  • 181
  • 302