1

I've written a generic timer class that uses the std::chrono time for the timer. This is a code example that shows the issue:

#include <iostream>
#include <chrono>

template <typename Rep, typename TimeType>
class Timer {
  public:
    Timer(const std::chrono::duration<Rep, TimeType> timerLength);
    ~Timer() = default;
  private:
    std::chrono::duration<Rep, TimeType> _timerLength;
};

template <typename Rep, typename TimeType>
Timer<Rep, TimeType>::Timer(const std::chrono::duration<Rep, TimeType> timerLength) : _timerLength{timerLength} {}

int main()
{
    constexpr int time_ms = 1000;

    Timer timer(std::chrono::milliseconds(time_ms));

    return 0;
}

This code results in the error: error: deduced class type ‘Timer’ in function return type.

This error can be removed by placing an actual int directly in the timer in main:

Timer timer(std::chrono::milliseconds(1000));

Additionally, this error can be removed by casting the time_ms parameter to an integer:

Timer timer(std::chrono::milliseconds(`static_cast<int>(time_ms)));

I expected the same result of an integer variable and casting an integer to an integer.

This error cannot be removed by removing the constexpr of the time_ms variable.

My question is: What are the differences between an integer variable and casting an integer to an integer (as well as inserting the number directly in the std::chrono::milliseconds())? And why does it make a difference in the first place?

Joost Baars
  • 84
  • 10
  • 3
    Does this answer your question? [Most vexing parse](https://stackoverflow.com/questions/38951362/most-vexing-parse) – JaMiT Apr 02 '20 at 14:02
  • `{}` will save you from the Most Vexing Parse: `Timer timer{std::chrono::milliseconds(time_ms)}`. – Howard Hinnant Apr 02 '20 at 14:03

1 Answers1

2

You are a victim of a vexing parse. With -Wall clang will even warn about that

source>:24:16: warning: parentheses were disambiguated as a function declaration [-Wvexing-parse]

    Timer timer(std::chrono::milliseconds(time_ms));

               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

and suggests a fix as well.

<source>:24:17: note: add a pair of parentheses to declare a variable

    Timer timer(std::chrono::milliseconds(time_ms));

                ^

                (                                 )

But you can disambiguate in other ways as well.

Timer timer{std::chrono::milliseconds(time_ms)};
Timer timer(std::chrono::milliseconds{time_ms});
auto timer = Timer(std::chrono::milliseconds(time_ms));
Timer timer(static_cast<std::chrono::milliseconds>(time_ms));

as well as putting an int literal in the expression, or explicitly casting to an int, as you noticed yourself.

cigien
  • 57,834
  • 11
  • 73
  • 112