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?
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.