Raw and Cooked

Contents[Show]

C++11 has user-defined literals for characters, C strings, integers and floating point numbers. For integers and floating point numbers they are available in raw and cooked form. Thanks to C++14 we have built-in literals for binary numbers, C++ strings, complex numbers, and time units.

 

The four user-defined literals

After the example in the last post user-defined literals I will provide - as promised - in this post the details. To make my intention clear here are the literal types including the raw and cooked variations

RawAndCookedEng

How should you read the table? The data type character has the form character_suffix. An example is 's'_c. The compiler tries to invoke the literal operator operator"" _c('s'). The character is in this case of the type char. C++ supports in addition to the data type char the data types wchar_t, char16_t, and char32_t. You can use this types as base for your C string. I used in the table a char. The table shows that the compiler maps the C string "hi"_i18 to the literal operator operator"" _i18n("hi",2). 2 is the length of the c string.

The compiler can map integers or floating point numbers to integers (unsigned long long int) or floating point numbers (long double) but the compiler can also map them to C strings. The first variant is called cooked form; the second variant raw form. The compiler will use the raw form if the literal operator wants its arguments as C string. If not, it uses the cooked form. If you implement both versions, the compiler will choose the cooked form.

Admittedly, in the last lines is a lot of confusion potential. Therefore, I sum all up from the perspective of the signatures in the following table. The first column has the signature of the literal operator, the second column the type of the user-defined literal, and the last column an example for a user-defined literal that fits the signature of the literal operator.

literaleSignaturEng

Calculate it once more

I calculated in the post user-defined literals how many meters I have to go by car in average per week. I made my calculation based on user-defined literals of the type long double in the cooked form. To make my calculation in the raw from I have simply to adjust the literal operators.

It's only necessary to convert the arguments of the literal operator from type C string to long double. That is quite easy to do with the new function std::stold.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// unit.h

#ifndef UNIT_H
#define UNIT_H

#include <distance.h>

namespace Distance{

  namespace Unit{
    MyDistance operator "" _km(const char* k){
      return MyDistance(1000* std::stold(k));
    }
    MyDistance operator "" _m(const char* m){
      return MyDistance(std::stold(m));
    }
    MyDistance operator "" _dm(const char* d){
      return MyDistance(std::stold(d)/10);
    }
    MyDistance operator "" _cm(const char* c){
      return MyDistance(std::stold(c)/100);
    }
  }
}

#endif

 

Either I have not to touch the class MyDistance.

 

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
// distance.h

#ifndef DISTANCE_H
#define DISTANCE_H

#include <iostream>
#include <ostream>


namespace Distance{
  class MyDistance{
    public:
      MyDistance(double i):m(i){}

      friend MyDistance operator+(const MyDistance& a, const MyDistance& b){
        return MyDistance(a.m + b.m);
      }
      friend MyDistance operator-(const MyDistance& a,const MyDistance& b){
        return MyDistance(a.m - b.m);
      }
	  
	  friend MyDistance operator*(double m, const MyDistance& a){
	    return MyDistance(m*a.m);
	  }
	  
	  friend MyDistance operator/(const MyDistance& a, int n){
	    return MyDistance(a.m/n);
	  }
	  
      friend std::ostream& operator<< (std::ostream &out, const MyDistance& myDist){
        out << myDist.m << " m";
        return out;
      }
	private:
	  double m;
	  
  };
  
}
  
Distance::MyDistance getAverageDistance(std::initializer_list<Distance::MyDistance> inList){
  auto sum= Distance::MyDistance{0.0};
  for (auto i: inList) sum = sum + i ;
  return sum/inList.size(); 
}


#endif

 

Nor does the main program need a modification.

 

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
// average.cpp

#include <distance.h>
#include <unit.h>

using namespace Distance::Unit;

int main(){

  std:: cout << std::endl;

  std::cout << "1.0_km: " << 1.0_km << std::endl;
  std::cout << "1.0_m: " << 1.0_m << std::endl;
  std::cout << "1.0_dm: " << 1.0_dm << std::endl;
  std::cout << "1.0_cm: " << 1.0_cm << std::endl;
  
  std::cout << std::endl;

  std::cout << "0.001 * 1.0_km: " << 0.001 * 1.0_km << std::endl;
  std::cout << "10 * 1_dm: " << 10 * 1.0_dm << std::endl;
  std::cout << "100 * 1.0cm: " << 100 * 1.0_cm << std::endl;
  std::cout << "1_.0km / 1000: " << 1.0_km / 1000 << std::endl;

  std::cout << std::endl;
  std::cout << "1.0_km + 2.0_dm +  3.0_dm + 4.0_cm: " << 1.0_km + 2.0_dm +  3.0_dm + 4.0_cm << std::endl;
  std::cout << std::endl;
  
  auto work= 63.0_km;
  auto workPerDay= 2 * work;
  auto abbrevationToWork= 5400.0_m;
  auto workout= 2 * 1600.0_m;
  auto shopping= 2 * 1200.0_m;
  
  auto distPerWeek1= 4*workPerDay-3*abbrevationToWork+ workout+ shopping;
  auto distPerWeek2= 4*workPerDay-3*abbrevationToWork+ 2*workout;
  auto distPerWeek3= 4*workout + 2*shopping;
  auto distPerWeek4= 5*workout + shopping;

  std::cout << "distPerWeek1: " << distPerWeek1 << std::endl;
  
  auto averageDistance= getAverageDistance({distPerWeek1,distPerWeek2,distPerWeek3,distPerWeek4});
  std::cout<< "averageDistance: " << averageDistance << std::endl;
  
  std::cout << std::endl;

}

 

Of course, the result is the same.

 average

 

New built-in literals with C++14

C++ added with C++14 a few new built-in literals. These are built-in literals for binary numbers, C++ strings, complex numbers, time unites. At first as ever the overview.

CppLiteralsEng

You have to keep a few special rules in mind. The binary numbers start with the prefix 0b. The built-in literals have no underscore. That is different from the user-defined literals. C++ support with C++14 the first time a C++ string literal. So far C++ supports only C string literals. That means for example that you always have to use a C string literal to initialize a C++ string. That was very strange. The time literals are very convenient because they implicitly know their unit. They are of the type std::chrono::duration.

The base unit for time is the second. My 16 years old son often complains that its school day is so exhausting. Of course ehe question arises. How many seconds does my son need for a typical school day? The program gives the answer.

 

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// literals.cpp

#include <iostream>
#include <chrono>

using namespace std::literals::chrono_literals;

int main(){

  std::cout << std::endl;

  auto schoolHour= 45min;

  auto shortBreak= 300s;
  auto longBreak= 0.25h;

  auto schoolWay= 15min;
  auto homework= 2h;

  auto schoolDayInSeconds= 2*schoolWay + 6 * schoolHour + 4 * shortBreak + longBreak + homework;
  
  std::cout << "School day in seconds: " << schoolDayInSeconds.count() << std::endl;
  
  std::cout << "School day in minutes: " << schoolDayInSeconds.count() / 60 << std::endl;
  
  std::cout << "School day in hours: " << schoolDayInSeconds.count() / 3600 << std::endl;

  std::cout << std::endl;

 

I think the program is totally self explanatory. The suffixes are expressive enough. Making the correct additions is the job of the compiler. The time literals support the base arithmetic addition, subtraction, multiplication, division, and modulo operation.

I have no C++14 compliant compiler to my disposal. Not really an issue. The online compiler on en.cppreference.com gives me the answers

My son need 27300 seconds for all his task releated to school. This is almost a typically working day in Germany of about 8 hours.

 schoolDay

What's next?

The classical enumerations (enum) in C++ have three big disadvantages.

  1. They convert implicitly to int.
  2. They introduce their enumerators into the enclosing scope.
  3. The type of the enumerators can not be defined.

In particular the characteristics 1 and 2 are often a reason for bad surprises. The new strong-typed enumerations clear off with this issues. Read about it in the next post.

 

 

 

 

 

 

 

 

title page smalltitle page small Go to Leanpub/cpplibrary "What every professional C++ programmer should know about the C++ standard library".   Get your e-book. Support my blog.

 

Comments   

0 #1 Jame 2016-11-04 15:15
Very soon this website will be famous among all blogging visitors, due tto
it's goood articles
Quote
0 #2 Raymon 2016-11-04 15:24
Hi there to all, since I am truly keen of reading this webpage's post to be
updated on a regular basis. It carries good data.
Quote
0 #3 Uwe 2016-11-07 22:18
I conceive this web site has got ssome real fantasstic information for everyone :D.
Quote
0 #4 Bart 2016-11-10 16:17
I like this website very much, Its a rral nice post to rad and obtain info.
Quote
0 #5 https://twitter.com/ 2016-11-13 23:22
Wow, superb weblog layout! How long have you ever been running a blog for?
you made blogging look easy. The whole look of your website is excellent,
let alone the contrent material![X-N-E-W-L-I-N-S-P-I-N-X]I just couldn't depart
your website prior to suggesting that I extremely enjoyed the standard information a person supply on your visitors?
Is going to be back ceaselessly to investigate cross-check new posts.
Quote
0 #6 Scarlett 2016-11-19 22:59
I am not sure where you're getting your information, but good topic.
I needs to spend some time learning more or understanding more.
Thanks for mwgnificent info I was looking for
his inforjation for my mission.
Quote
0 #7 Augusta 2016-11-28 12:58
I like this web site very much so much suuperb information.
Quote

Add comment


Support my blog by buying my E-book

Latest comments

Modernes C++

Subscribe to the newsletter

Including two chapters of my e-book
Introduction and Multithreading

Blog archive

Source Code

Visitors

Today 1022

All 227036

Currently are 73 guests and no members online