Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can I have a ratio object in C++

Tags:

c++

c++11

chrono

I am learning ratio in C++11. According to cplusplus.com and the book Professional C++ 2nd (the following paragraph is an excerpt from it).

The numerator and denominator of a rational number are represented as compile time constants of type std::intmax_t. Because of the compile time nature of these rational numbers, using them might look a bit complicated and different than usual. You cannot define a ratio object the same way as you define normal objects, and you cannot call methods on it. You need to use typedefs.

That means I have to write

typedef ratio<1,3> one_third;

instead of

ratio<1,3> one_third;

But I find that these two ways of write ratio are both working. And I can access members of ratio using either . or ::.

Question 1. Are the cplusplus.com and the Professional C++ book wrong?

The following snippet is from cplusplus.com example.

typedef std::ratio<1,3> one_third;
typedef std::ratio<2,4> two_fourths;
typedef std::ratio_add<one_third,two_fourths> sum;
std::cout << sum::den << std::endl;

Question 2. However, I got an error (with VS 2012)

error C2039: 'den' : is not a member of 'std::ratio_add<_R1,_R2>'

According to the comments, using typedef ratio_add<one_third, two_fourths>::type sum is more portable.

like image 301
champaign Avatar asked Jul 28 '14 22:07

champaign


1 Answers

You don't have to use typedefs, but as the book says, <ratio> deals with compile time math, and the meta-functions defined within it take type template arguments.

If you don't use a typedef you're creating an instance of std::ratio<1,3> named one_third, which is not suitable for passing as a type argument. In that case you'll need to use decltype to get to the appropriate type that can be passed to ratio_add

std::ratio<1,3> one_third;
std::ratio<2,4> two_fourths;
std::ratio_add<decltype(one_third), decltype(two_fourths)> sum;
std::cout << decltype(sum)::den << std::endl;

Live demo


The error message you're seeing is because the ratio_add (and other similar meta-functions') implementation is not standard conforming on VS2012 due to lack of support for alias templates. As described in the linked bug report, the workaround is to use the nested type type.

typedef std::ratio_add<one_third,two_fourths>::type sum;
std::cout << sum::den << std::endl;
like image 129
Praetorian Avatar answered Nov 15 '22 07:11

Praetorian