44

I have just seen this black magic in folly/ManualExecutor.h

TimePoint now_ = now_.min();

After I grep'ed the whole library source code, I haven't seen a definition of the variable now_ anywhere else than here. What's happening here? Is this effectively some sort recursive variable declaration?

FCR
  • 1,103
  • 10
  • 25
  • 3
    I think this question could be improved, if you provided a link to documentation of `TimePoint` (if available in the web), or added declaration of `TimePoint::min()` (copy-paste the relevant lines from .h file, which you must have if it compiles). – hyde Dec 07 '16 at 13:49
  • See also: http://stackoverflow.com/questions/325555/c-static-member-method-call-on-class-instance – Cody Gray - on strike Dec 07 '16 at 13:56
  • 9
    yet another way to obfuscate code.... – A.S.H Dec 07 '16 at 14:07
  • 1
    Looks a bit like `Runtime runtime = Runtime.getRuntime();` in java... – MD XF Dec 07 '16 at 21:41
  • @MDXF: It is.... but avoiding repeating the typename, which might be quite long if it needs template arguments or is qualified. – Ben Voigt Dec 07 '16 at 21:46
  • A search for TimePoint would have done you more good. – Mikel F Dec 07 '16 at 22:25
  • FWIW, I happened across this stackoverflow question and patched this to be less needlessly opaque: https://github.com/facebook/folly/commit/b727acf4391c4f3300ab0348bf1032a02999b408#diff-30beff23525b19a3404dbfc49d84d25f – Louis Brandy May 26 '17 at 17:05

2 Answers2

63

That code is most likely equal to this:

TimePoint now_ = TimePoint::min();

That means, min() is a static method, and calling it using an instance is same as calling it like this, the instance is used just for determining the type. No black magic involved, that's just two syntaxes for doing the same thing.

As to why the code in question compiles: now_ is already declared by the left side of the line, so when it's used for initialization on the right side, compiler already knows its type and is able to call the static method. Trying to call non-static method should give an error (see comment of @BenVoigt below).

As demonstrated by the fact that you had to write this question, the syntax in the question is not the most clear. It may be tempting if type name long, and is perhaps justifiable in member variable declarations with initializer (which the question code is). In code inside functions, auto is better way to reduce repetition.

hyde
  • 60,639
  • 21
  • 115
  • 176
  • 21
    From the compiler's perspective, the two ways of writing this are equivalent. In a code review, only one of them would be acceptable. I leave it as an exercise for the reader to guess which one. – Cody Gray - on strike Dec 07 '16 at 13:53
  • 12
    @CodyGray Yes, everyone knows your hatred of the four dots of evil. Be reasonable Cody: sometimes `::` is the best choice! – Yakk - Adam Nevraumont Dec 07 '16 at 19:47
  • 5
    Analysis of non-static case -- value computation of the initializer is ordered before the copy constructor call (this syntax is copy-initialization), therefore the constructor has not begun execution, therefore the object's lifetime has not started. Section 3.8 of the Standard says that "Before the lifetime of an object has started but after the storage which the object will occupy has been allocated, ny glvalue that refers to the original object may be used but only in limited ways. The program has undefined behavior if: the glvalue is used to call a non-static member function of the object." – Ben Voigt Dec 07 '16 at 21:44
  • The code quoted by the OP is actually a non-static data member, where `auto` is not available. – T.C. Dec 08 '16 at 06:53
  • @T.C. Hmm. Can you explain more? Looks like method *static constexpr time_point min();* to me, based on Mikel F's answer. – hyde Dec 08 '16 at 06:59
  • @hyde `min` is static. The problem is that `now_` is actually a non-static data member of some class, and `now_.min()` is actually its default member initializer. – T.C. Dec 08 '16 at 07:00
  • @T.C. Ah! I guess that might warrant editing the question a bit to give right context without clicking the link. Thanks. – hyde Dec 08 '16 at 07:03
14

Digging into the code shows that TimePoint is an alias for chrono::steady_clock::time_point, where min() is indeed a static method that returns the minimum allowable duration:

http://en.cppreference.com/w/cpp/chrono/time_point/min

Mikel F
  • 3,567
  • 1
  • 21
  • 33