Concepts of Programming Languages C++ Template Metaprogramming Michiel Magendans Robin Ganpat Jelmer Van Nuss Hugo Heemskerk Thomas Dirkse
Total Page:16
File Type:pdf, Size:1020Kb
Concepts of programming languages C++ Template Metaprogramming Michiel Magendans Robin Ganpat Jelmer van Nuss Hugo Heemskerk Thomas Dirkse [Faculty of Science Information and Computing Sciences] 1 Metaprogramming Why program metaprograms? I Programs writing programs, we’ve seen this before I An introduction, not limited to C++ I Very useful in the real world! I Can go horribly wrong.. [Faculty of Science Information and Computing Sciences] 2 Hypothetical company I We make administration software! Exciting! I Web application that allows us to interact with a database I Some business logic when interacting with the database [Faculty of Science Information and Computing Sciences] 3 What do we want to make? I CRUD (Create, Read, Update, Delete) software requires insert, update, etc. functions/statements I A database table is essentially a small set of named parameters, which themselves can have parameters I Boilerplate heaven! So much code to write! I Functions, getters, setters, loving it I Always write the general case, don’t abstract [Faculty of Science Information and Computing Sciences] 4 How to monetize this I Charge customer by programmer hour I Hire lots more programmers I Outsource I Profit! [Faculty of Science Information and Computing Sciences] 5 Lots of work though I Work is getting cumbersome, let’s try metaprogramming Figure 1: [Faculty of Science Information and Computing Sciences] 6 Let’s reduce our workload I Idea: Write a code generator! It writes the code for us! I Set of 12 database table parameters to create 2k LoC, spread out over 16 files I Stringly typed, some extra xml, no documentation necessary I Manually add every generated file to a complex file tree [Faculty of Science Information and Computing Sciences] 7 More profit! I We have now guaranteed ourselves work for years to come! I When the generator changes, we will have to retroactively update all previously generated files I A job that would normally cost 30 minutes will now cost 10 hours at the minimum: we will make so much money! I Technical debt? Owed by our customers, to us? Brilliant! [Faculty of Science Information and Computing Sciences] 8 Derp Figure 2: [Faculty of Science Information and Computing Sciences] 9 But.. why? I This is not due to incompetence! I It’s a set of common business problems coming together in an unfortunate way I Strategy problems: no short-term financial incentives to work efficiently, historical artifacts I People problems: Unwillingness to change, attachment to own code, egos I People problems are usually caused by strategy problems [Faculty of Science Information and Computing Sciences] 10 What should happen in the business I Different business model can make a huge difference! I Upfront single-price purchase I SaaS (Software as a Service, subscription fee) I Different languages can prevent different types of situations from happening in the first place [Faculty of Science Information and Computing Sciences] 11 What should happen in the tech I DRY: Don’t Repeat Yourself I Make the generic case trivial I Extensibility: allow boilerplate to be written iff necessary, and let it override very specific parts of the meta program I Never let programmers touch the generated code - it might as well not exist I Allow business logic to interact with metaprogrammed classes as if they were written manually I IDE/text editor support, humans are not good at spotting syntax errors [Faculty of Science Information and Computing Sciences] 12 In OOP? I You can do this in pure OOP too! I However: requires multifaceted investment in framework I Business logic becomes harder to separate from the framework I Onboarding/training new developers becomes harder I Language/IDEs/autocompletion might not be cooperative [Faculty of Science Information and Computing Sciences] 13 There are costs and obstacles I If your chosen language does not support any types of metaprogramming, expect heavy costs, or rather don’t try at all I Requires a higher upfront investment regardless I Can be tougher to debug I Small changes in the meta program affect everything [Faculty of Science Information and Computing Sciences] 14 Takeaway I Metaprogramming can be extremely useful and extremely damaging if done wrong I Choice in language and programming practices greatly affects how a business is, and can berun I The opposite is also true! I The question you need to ask yourself when choosing a language is: What mistakes will I allow the company’s programmers to make? What bugs are worth their time? [Faculty of Science Information and Computing Sciences] 15 C++ Templates What are they? I A feature of C++ which allows functions and classes to operate with generic types. I Generics are generic until the types are substituted for them at runtime. Templates are specialized at compile time. I Templates allow explicit specialization. I Type substition is done during compilation, not run-time. I There are Function Templates and Class Templates [Faculty of Science Information and Computing Sciences] 16 Function Templates - A Simple example A possible Max()-function defined in C++: int Max(int a, int b) { return a > b ? a : b; } Result: cout << Max(23, 40); #> 40 [Faculty of Science Information and Computing Sciences] 17 A Simple example The same function as previous slide, but for the double data type. double Max(double a, double b) { return a > b ? a : b; } Result: cout << Max(12.5, 48.21); #> 48.21 [Faculty of Science Information and Computing Sciences] 18 So what’s the difference? It is exactly the same logic, but the data type is difference. This is where Templates come in handy! [Faculty of Science Information and Computing Sciences] 19 The Max()-function using Function Templates template <typename T> T GetMax(T a, T b) { return a > b ? a : b; } Result: cout << Max(23, 40); #> 40 This invokes the template function with T == int. The function returns a value of int type. [Faculty of Science Information and Computing Sciences] 20 Class templates I Function templates allow writing generic functions that will work on many types. I The same idea applies for class templates. [Faculty of Science Information and Computing Sciences] 21 A Simple example (1) template <typename T> class ValueComparer { T first, second; public: ValueComparer(T a, T b) { first = a; second = b; } T getBiggerOne(); }; [Faculty of Science Information and Computing Sciences] 22 A Simple example (2) getBiggerOne() is a member function of the class template. Here is the implementation: template <typename T> T ValueComparer<T>::getBiggerOne() { return first > second ? first : second; } Result: ValueComparer <int> vc_int(69, 34); ValueComparer <double> vc_double(29.23, 49.133); cout << vc_int.getBiggerOne() << endl; cout << vc_double.getBiggerOne(); #> 69 [Faculty of Science #> 49.133 Information and Computing Sciences] 23 Template Specialization In some cases you may want a specific implementation for a specific data type. This is where Template Specialization comes in. [Faculty of Science Information and Computing Sciences] 24 Template Specialization ValueComparer Template definition from previous slide: template <typename T> class ValueComparer { T first, second; public: ValueComparer(T a, T b) { first = a; second = b; } T getBiggerOne(); } [Faculty of Science Information and Computing Sciences] 25 Lets say we want to create a specific implementation for the data type: string. The function getBiggerOne() should return the string with the biggest length. template <typename T> T ValueComparer<T>::getBiggerOne() { return first > second ? first : second; } template <> string ValueComparer<string>::getBiggerOne() { cout << "We can do even more things here." << endl; return first.length() > second.length() ? first : second; } [Faculty of Science Information and Computing Sciences] 26 The results ValueComparer <int> vc_int(69, 34); ValueComparer <double> vc_double(29.23, 49.133) ValueComparer <string> vc_string("aaa", "bb"); std::cout << vc_int.getBiggerOne() << endl; std::cout << vc_double.getBiggerOne(); std::cout << vc_string.getBiggerOne(); #> 69 #> 49.133 #> We can do even more things here. #> aaa [Faculty of Science Information and Computing Sciences] 27 Generic Programming I Polymorphism I Widely used concept in OO languages I Used to associate different specific behaviours with a single generic notation [Faculty of Science Information and Computing Sciences] 28 I In C++, you make use of inheritance and virtual functions Figure 3: C++ Polymorphism [Faculty of Science Information and Computing Sciences] 29 class GeoObj { public: virtual void draw() const = 0; virtual Coordinate center_of_gravity() const = 0; }; class Circle : public GeoObj { public: // Both methods implementations in .cpp file. virtual void draw() const; virtual Coordinate center_of_gravity() const; } [Faculty of Science Information and Computing Sciences] 30 I After creating the concrete objects, access the different concrete implementations using references or pointers to base class. // Draw any GeoObj void draw_shape(GeoObj const& shape) { shape.draw(); } [Faculty of Science Information and Computing Sciences] 31 // draw a collection of all kinds of shapes void draw_shapes(std::vector<GeoObj*> const& elems) { for(unsigned int i = 0; i < elems.size(); ++i) elems[i]->draw(); } // calculate the distance using the centers // of the shapes Coordinate distance_between(GeoObj const& x1, GeoObj const& x2) { return x1.center_of_gravity() - x2.center_of_gravity; } [Faculty of Science Information and Computing Sciences] 32 Dynamic Polymorphism