c++c++11c++-chronomost-vexing-parse

std::chrono::time_point compiler error when converting from a variable


I have a variable of type long long that represents a time point in nanoseconds.

I'm trying to wrap it using std::chrono::time_point yet the compiler (VS 2017) is giving me troubles.

here is a code that compiles:

std::chrono::time_point<std::chrono::steady_clock> tpStart(std::chrono::nanoseconds(10ll));
std::chrono::time_point<std::chrono::steady_clock> tpEnd = std::chrono::steady_clock::now();
double d =  std::chrono::duration<double>(tpEnd - tpStart).count();

Now if i switch the value 10ll with a variable, the line that computes the duration fails to compile:

constexpr long long t = 10ll;
std::chrono::time_point<std::chrono::steady_clock> tpStart(std::chrono::nanoseconds(t));
std::chrono::time_point<std::chrono::steady_clock> tpEnd = std::chrono::steady_clock::now();
double d =  std::chrono::duration<double>(tpEnd - tpStart).count();

Here is the error code:

error C2679: binary '-': no operator found which takes a right-hand operand of type 'overloaded-function' (or there is no acceptable conversion)

Any Idea why is this happening? how can I convert a variable of type long long to a std::chrono::time_point?


Solution

  • TLDR : It's a most vexing parse case

    prog.cc:8:59: warning: parentheses were disambiguated as a function declaration [-Wvexing-parse]
    std::chrono::time_point<std::chrono::steady_clock> tpStart(std::chrono::nanoseconds(t));
    

    Fix with {} instead of ()

    constexpr long long t = 10ll;
    std::chrono::time_point<std::chrono::steady_clock> tpStart{std::chrono::nanoseconds{t}};
    std::chrono::time_point<std::chrono::steady_clock> tpEnd = std::chrono::steady_clock::now();
    double d =  std::chrono::duration<double>(tpEnd - tpStart).count();
    

    Why it's a most vexing parse?

    std::chrono::time_point<std::chrono::steady_clock> pStart  (std::chrono::nanoseconds(t));
    //                  ^^^^ Type 1 ^^^^^              ^name^      ^^^^ Type 2 ^^^^
    

    So we can reproduce with :

    constexpr long long t = 10ll;
    int fail (double (t) );
    fail = 6; // compilation error here
    

    Why ? Let's remove some noise :

    int fail (double (t) );
    //  <=> 
    int fail (double t);
    // <=>
    int fail (double) ; // Most vexing parse.
    

    We can fix it by switching to {}

    int Ok {double {t} };