#template metaprogramming
Explore tagged Tumblr posts
Text
image credit
10 notes
·
View notes
Photo
An Overview of Template Metaprogramming in C++ Template metaprogramming (TMP) is a powerful and versatile programming technique in C++ that allows developers to generate code at compile time. It has been widely used to create efficient and reusable components, as well as to create domain specific languages. The main idea behind TMP is to use templates as a way to generate code at compile-time, rather than writing it out manually. This is done by writing template classes and functions that generate code based on the template arguments they are given. This allows developers to write generic code that can be used in a variety of situations, while still allowing for the flexibility to specialize the code for specific applications. The process of template metaprogramming involves the following steps: 1. Writing a template class or function that takes template parameters. 2. Writing code within the template class or function https://digitaltutorialsapp.com/an-overview-of-template-metaprogramming-in-c/?utm_source=tumblr&utm_medium=socialtumbdigitutorials&utm_campaign=camptumbdigitutorials
0 notes
Note
5 best things about C++ that aren't constexpr
5 worst things about C++
Best compared to what though
You always gotta look at what the competition forgot to bring.
--- Best:
RAII/Deterministic destruction
const
templates and template metaprogramming (in the interest of fairness to other languages that cannot pretend to compete I will make this one item)
perf
C Interop
--- Meh:
C Interop
--- Worst:
C interop
ABI back compat is killing me slowly
UB, especially UB NDR fuck NDR all my homies hate NDR
the "noexcept" specifier is hot garbage and yet it could have been so good
the build system
the build system
the build system
the build system
the build system
the build system
the build system
the build system
18 notes
·
View notes
Text
#codetober 2023. 10. 05.
So the question arises:
propaganda:
C++: my strong suit, will make progress quicker, kinda know what to do next. Too familiar tbh.
Rust: the perfect opportunity to finally try it in a medium sized project, building up the knowledge in the go. Probably will be very slow in the beginning, might discourage me.
Today's goal is coming up some basic design (language independent) on the whiteboard to see the connections and interfaces I might need.
I want to decouple the "business logic" from the visualisation as a design principle. Also want to keep things simple and performant.
What's your favorite programming language? Why?
Easy question: C++
The expressiveness of the template metaprogramming is unparalleled. No other language I know of can do the same with the same flexibility. I recently wrote a Tower of Hanoi solver that creates the steps for the solution in compile time (and gives the compiler error message of the solution to prove it is done before anything is ever ran). It even has an addition to generate the steps and the states it goes through as ASCII art at compile time using TMP. And this is not even that advanced usage, just a little toy example.
It's somewhat a love-hate relationship.
17 notes
·
View notes
Text
Day 1 of whatever the fuck im gonna do here
Metaprogramming, what is it? Programing a program, that programs the program
sounds like some bullshit AI thats supposted to destroy whole workforce, but no, its just some tool to write less stuff, and maintain code better, but errors are even worse
How the FUCK do i do it in c++? Templates and concepts, what are those?
Template, is what ready code will do like
fuck does that mean?
we create template, that has typename T (which can take any variable like int, char etc), returned type and name of function with parameters, this one will take value of any variable type, and print it to console, cool right?
NO, what if you wanna make function that adds 2 numbers? you can make bilion overloaded functions, or you could make template, that will fucking die as soon as you give it string or something, thats what Concepts are for.
example of using metaprograming stuff, to only add float types
output:
i was gonna make actual concepts, but c++ refuses to work so lets end here, my sanity is low, i will make next post when i recharge or something
3 notes
·
View notes
Text
Which topic are taught under c++ course
A C++ course typically covers a range of topics designed to introduce students to the fundamentals of programming, as well as more advanced concepts specific to C++. Here's a breakdown of common topics:
1. Introduction to Programming Concepts
Basic Programming Concepts: Variables, data types, operators, expressions.
Input/Output: Using cin, cout, file handling.
Control Structures: Conditional statements (if, else, switch), loops (for, while, do-while).
2. C++ Syntax and Structure
Functions: Definition, declaration, parameters, return types, recursion.
Scope and Lifetime: Local and global variables, static variables.
Preprocessor Directives: #include, #define, macros.
3. Data Structures
Arrays: Single and multi-dimensional arrays, array manipulation.
Strings: C-style strings, string handling functions, the std::string class.
Pointers: Pointer basics, pointer arithmetic, pointers to functions, pointers and arrays.
Dynamic Memory Allocation: new and delete operators, dynamic arrays.
4. Object-Oriented Programming (OOP)
Classes and Objects: Definition, instantiation, access specifiers, member functions.
Constructors and Destructors: Initialization of objects, object cleanup.
Inheritance: Base and derived classes, single and multiple inheritance, access control.
Polymorphism: Function overloading, operator overloading, virtual functions, abstract classes, and interfaces.
Encapsulation: Use of private and public members, getter and setter functions.
Friend Functions and Classes: Use and purpose of friend keyword.
5. Advanced Topics
Templates: Function templates, class templates, template specialization.
Standard Template Library (STL): Vectors, lists, maps, sets, iterators, algorithms.
Exception Handling: try, catch, throw, custom exceptions.
File Handling: Reading from and writing to files using fstream, handling binary files.
Namespaces: Creating and using namespaces, the std namespace.
6. Memory Management
Dynamic Allocation: Managing memory with new and delete.
Smart Pointers: std::unique_ptr, std::shared_ptr, std::weak_ptr.
Memory Leaks and Debugging: Identifying and preventing memory leaks.
7. Algorithms and Problem Solving
Searching and Sorting Algorithms: Linear search, binary search, bubble sort, selection sort, insertion sort.
Recursion: Concepts and use-cases of recursive algorithms.
Data Structures: Linked lists, stacks, queues, trees, and graphs.
8. Multithreading and Concurrency
Thread Basics: Creating and managing threads.
Synchronization: Mutexes, locks, condition variables.
Concurrency Issues: Deadlocks, race conditions.
9. Best Practices and Coding Standards
Code Style: Naming conventions, commenting, formatting.
Optimization Techniques: Efficient coding practices, understanding compiler optimizations.
Design Patterns: Common patterns like Singleton, Factory, Observer.
10. Project Work and Applications
Building Applications: Developing simple to complex applications using C++.
Debugging and Testing: Using debugging tools, writing test cases.
Version Control: Introduction to version control systems like Git.
This comprehensive set of topics equips students with the skills needed to develop efficient, robust, and scalable software using C++. Depending on the course level, additional advanced topics like metaprogramming, networking, or game development might also be covered.
C++ course in chennai
Web designing course in chennai
full stack course in chennai
0 notes
Text
C++ Programming Assignment Help
C++ Programming Assignment Help to support you in achieving the best grades. It can be intimidating, especially for those who are unfamiliar with the nuances of this potent language. Do not worry; we are here to assist you in navigating the confusing world of pointers, classes, and templates in your C++ programming project. With a wealth of experience, our knowledgeable staff of experts is prepared to help you grasp C++ ideas and tackle difficult assignments. We cover everything from fundamental syntax to complex subjects like multithreading and template metaprogramming. Say goodbye to sleepless nights and hello to top-notch scores. Allow our assistance with C++ programming assignments to serve as your guide in the realm of exceptional coding.
0 notes
Text
https://gradespire.com/c-programming-assignment-help/
C++ Programming Assignment Help to support you in achieving the best grades. It can be intimidating, especially for those who are unfamiliar with the nuances of this potent language. Do not worry; we are here to assist you in navigating the confusing world of pointers, classes, and templates in your C++ programming project. With a wealth of experience, our knowledgeable staff of experts is prepared to help you grasp C++ ideas and tackle difficult assignments. We cover everything from fundamental syntax to complex subjects like multithreading and template metaprogramming. Say goodbye to sleepless nights and hello to top-notch scores. Allow our assistance with C++ programming assignments to serve as your guide in the realm of exceptional coding.
0 notes
Text
Intel FPGAs speed up databases with oneAPI and SIMD orders
A cutting-edge strategy for improving single-threaded CPU speed is Single Instruction Multiple Data (SIMD).
FPGAs are known for high-performance computing via customizing circuits for algorithms. Their tailored and optimized hardware accelerates difficult computations.
SIMD and FPGAs seem unrelated, yet this blog article will demonstrate their compatibility. By enabling data parallel processing, FPGAs can boost processing performance with SIMD. For many computationally intensive activities, FPGA adaptability and SIMD efficiency are appealing.
High-performance SIMDified programming
SIMD parallel processing applies a single instruction to numerous data objects. Special hardware extensions can execute the same instruction on several data objects simultaneously.
SIMDified processing uses data independence to boost software application performance by rewriting application code to use SIMD instructions extensively.
Key advantages of SIMDified processing include:
Increased performance: SIMDified processing boosts computationally intensive software applications.
Integrability: Intrinsics and dedicated data types make SIMDified processing desirable.
SIMDified processing is available on many current processors, giving it a viable option for computational speed improvement.
Despite its benefits, SIMDified processing is not ideal for many applications. Applications with minimal data parallelism will not benefit from SIMDified processing. It is a convincing method for improving data-intensive software applications.
SIMD Portability Supports Heterogeneity
SIMD registers and instructions make up SIMD instruction sets. SIMD intrinsics in C/C++ are the best low-level programming method for performance.
Low-level programming in heterogeneous settings with different hardware platforms, operating systems, architectures, and technologies is difficult due to hardware capabilities, data parallelism, and naming standards.
Specialized implementations limit portability between platforms, hence SIMD abstraction libraries provide a common SIMD interface and abstract SIMD functions. These libraries use C++ template metaprogramming and function template specializations to translate to SIMD intrinsics and potential compensations for missing functions, which must be implemented.
C/C++ libraries let developers construct SIMD-hardware-oblivious application code and SIMD extension code with minimum overhead. Separating SIMD-hardware-oblivious code with a SIMD abstraction library simplifies both sides.
This method has promoted many SIMD libraries and abstraction layers to solve problems:
Examples of SIMD libraries
Google Highway (open-source)
Xsimd (C++ wrapper for SIMD instances)
Such libraries allow SIMDified code to be designed once and specialized for the target SIMD platform by the SIMD abstraction library. Libraries and varied design environments suit SIMD instructions and abstraction.
Accelerating with FPGAs
FPGAs speed software at low cost and power. Traditional FPGAs required a strong understanding of digital design concepts and specific languages like VHDL or Verilog. FPGA-based solutions are harder to access and more specialized than CPU or GPU-based computing platforms due to programming complexity and code portability. Intel oneAPI changes this.
Intel oneAPI is a software development kit that unifies CPU, GPU, and FPGA programming. It supports C++, Fortran, Python, and Data Parallel C++ (DPC++) for heterogeneous computing to improve performance, productivity, and development time.
Since Intel oneAPI can target FPGAs from SYCL/C++, software developers are increasingly interested in using them for data processing. FPGAs can be used with SIMDified applications by adding them as a backend to the SIMD abstraction library. This allows SIMD applications with FPGAs.
SIMD and FPGAs go together Annotations let the Intel DPC++ compiler synthesis C++ code into circuits and auto-vectorize data-parallel processing. Annotating and implementing code arrays as registers on an FPGA removes data access constraints and allows parallel processing from sink to source. This enables SIMD performance acceleration using FPGAs straightforward and configurable.
SIMD abstraction libraries are a logical choice for FPGA SIMD processing. As noted, the libraries support Intel and ARM SIMD instruction set extensions. TSL abstraction library simplifies FPGA SIMD instruction implementation in the following example. The scalar code specifies loading registers, and the pragma unroll attribute tells the DPC++ Compiler to implement all pathways in parallel in the generic element-wise addition example below.
This simple element-wise example has no dependencies, and comparable implementations will work for SIMD instructions like scatter, gather, and store. Optimization can also accelerate complex instructions.
A horizontal reduction requires a compile-time adder tree of depth ld(N), where N is the number of entries. Unroll pragmas with compile-time constants can implement adder trees in a scalable manner, as shown in the following code example.
Software that calls a library of comparable SIMD components can expedite SIMD instructions on Intel FPGAs by adding the examples above.
Intel FPGA Board Support Package adds system benefits. Intel FPGAs use a BSP to describe hardware interfaces and offer a kernel shell.
The BSP enables SYCL Universal Shared Memory (USM), which frees the CPU from data transfer management by exchanging data directly with the accelerator. FPGAs can be coprocessors.
The pre-compiled BSP generates only kernel logic live, reducing runtime.
Intel FPGAs are ideal for SIMD and streaming applications like current composable databases because to their C++/SYCL compatibility, CPU data transfer offloading, and pre-compiled BSPs.
SIMD/FPGA simplicity At SiMoDSIGMOD 2023 in Seattle, USA, Dirk Habich, Alexander Krause, Johannes Pietrzyk, and Wolfgang Lehner of TU Dresden presented their paper “Simplicity done right for SIMDified query processing on CPU and FPGA” on using FPGAs to accelerate SIMD instructions. The work, supported by Intel’s Christian Färber, illustrates how practical and efficient developing a SIMDified kernel in an FPGA is while achieving top performance.
The paper evaluated FPGA acceleration of SIMD instructions using a dual-socket 3rd-generation Intel Xeon Scalable processor (code-named “Ice Lake”) with 36 cores and a base frequency of 2.2 GHz and a BitWare IA-840f acceleration card with an Intel Agilex 7 AGF027 FPGA and 4x 16 GB DDR4 memories.
First, they gradually increased the SIMD instance register width to see how it affected maximum acceleration bandwidth. The first instance, a simple aggregation, revealed that the FPGA accelerator’s bandwidth improves with data width doubling until the global bandwidth saturates an ideal acceleration case.
The second scenario, a filter-count kernel with a data dependency in the last stage of the adder tree, demonstrated similar behavior but saturates earlier at the PCIe link width. Both scenarios demonstrate the considerable speeding gains of natively parallel instructions on a highly parallel architecture and suggest that wide memory accesses could sustain the benefits.
Final performance comparisons compared the FPGA and CPU. CPU and FPGA received the same multi-threaded AVX512-based filter-count kernel. As expected, per-core CPU bandwidth decreased as thread count and CPU core count grew. FPGA performance was peak across all workloads.
Based on this work, the TU Dresden and Intel team researched how to use TSL to use an FPGA as a bespoke SIMD processor.
Read more on Govidhtech.com
0 notes
Text
Istilah Umum Dalam Bahasa Program MacOS For Developer
Bahasa Program di Dalam Sistem Operasi MacOS
MacOS, sistem operasi khas dari Apple, telah memberikan dukungan yang luas terhadap berbagai bahasa pemrograman untuk menghasilkan aplikasi yang inovatif dan fungsional. Salah satu bahasa yang mengemuka dalam ekosistem MacOS adalah Swift. Dikembangkan oleh Apple sendiri, Swift telah menghadirkan perubahan signifikan dalam cara aplikasi dibangun di platform ini. Dengan sintaksis yang lebih intuitif dan mudah dipahami, Swift memungkinkan para pengembang untuk menghasilkan kode dengan kecepatan lebih tinggi dan risiko lebih rendah terhadap kesalahan. Selain itu, Swift juga menawarkan performa tinggi, membuat aplikasi MacOS menjadi responsif dan efisien. Selain Swift, bahasa pemrograman lain seperti Objective-C, Python, dan C++ juga berperan penting dalam membentuk ekosistem pengembangan MacOS yang kaya dan beragam.
Setiap bahasa pemrograman yang ada dalam dunia MacOS memiliki kekhasan dan keunggulan tersendiri, memberikan opsi bagi para pengembang untuk memilih sesuai dengan kebutuhan proyek. Dengan dukungan yang luas dari Apple, pengembang dapat mengoptimalkan potensi bahasa-bahasa ini untuk menciptakan aplikasi yang sesuai dengan standar desain dan performa yang diharapkan dalam ekosistem MacOS. Dari bahasa yang lebih klasik seperti Objective-C hingga bahasa modern seperti Swift, tersedia alat dan sumber daya yang diperlukan untuk menghadirkan pengalaman pengguna yang superior dan aplikasi yang luar biasa di dunia yang terus berkembang pesat ini. Okay, dalam postingan ini, kami akan mengajak anda mengenali beberapa istilah penting dari beberapa bahasa porgram di atas. Simak terus ulasan kami berikut ini!
Istilah Penting dalam Bahasa Program MacOS
Dan berikut adalah beberapa istilah penting yang terkait dengan masing-masing bahasa pemrograman yang telah disebutkan sebelumnya:
1. Swift
• Sintaksis - Tata cara penulisan kode dalam bahasa pemrograman yang ditetapkan.
• Type Inference - Kemampuan Swift untuk secara otomatis menentukan tipe data dari suatu variabel berdasarkan nilai yang diberikan.
• Optionals - Konsep dalam Swift yang mengizinkan variabel memiliki nilai yang tidak ada (nil), mengatasi masalah nilai kosong atau null.
• Playground - Lingkungan interaktif dalam Xcode yang memungkinkan pengembang untuk mencoba kode Swift tanpa perlu membuat aplikasi utuh.
2. Objective-C
• Message Passing - Cara komunikasi antara objek dalam Objective-C, di mana objek mengirim pesan satu sama lain.
• Interface dan Implementation Files - Pemisahan antara bagian deklarasi (interface) dan implementasi dari kelas dalam Objective-C.
• ARC (Automatic Reference Counting) - Mekanisme yang digunakan untuk mengelola alokasi dan pembebasan memori pada objek dalam Objective-C.
3. C++
• Classes dan Objects - Dasar dari pemrograman berorientasi objek dalam C++, dengan classes sebagai blueprint dan objects sebagai instance dari class.
• Pointers - Variabel yang menyimpan alamat memori dari variabel lain.
• Templates - Fitur dalam C++ yang memungkinkan pengembang membuat fungsi atau kelas yang dapat menerima tipe data yang berbeda tanpa perlu menulis kode baru.
4. Python
• Indentation - Penggunaan spasi atau tab untuk menunjukkan blok kode dalam Python.
• Pustaka (Library) dan Modul - Kode yang telah ditulis sebelumnya yang dapat digunakan kembali dalam program Python.
• Dynamic Typing - Kemampuan Python untuk menentukan tipe data variabel secara dinamis.
5. Java
• Class - Blueprint untuk objek dalam pemrograman berorientasi objek Java.
• Inheritance - Konsep di mana class baru dapat diwariskan sifat-sifat dan metode dari class yang sudah ada.
• JVM (Java Virtual Machine) - Lingkungan yang menjalankan kode Java pada berbagai platform.
6. Ruby
• Blocks - Potongan kode yang dapat digunakan sebagai argumen dalam metode Ruby.
• Gems - Paket-paket pustaka yang dapat diinstal dan digunakan dalam Ruby.
• Metaprogramming - Kemampuan Ruby untuk memanipulasi kode dalam waktu eksekusi.
7. JavaScript (via Electron)
• DOM (Document Object Model) - Representasi struktur HTML dan XML sebagai objek yang dapat dimanipulasi melalui JavaScript.
• Event Handling - Penggunaan JavaScript untuk menangani peristiwa (event) seperti klik tombol atau pengisian formulir.
8. Go (Golang)
• Goroutines - Fungsi-fungsi ringan yang dijalankan bersamaan dalam program Go.
• Channels - Mekanisme untuk komunikasi dan koordinasi antara goroutines.
• Structs - Tipe data yang memungkinkan pengembang mengelompokkan data dengan tipe yang berbeda dalam satu entitas.
9. Shell Scripting (Bash):
• Shell Commands - Perintah-perintah yang dieksekusi di terminal untuk berinteraksi dengan sistem operasi.
• Variables - Nama-nama yang digunakan untuk menyimpan nilai atau teks dalam skrip Bash.
10. Rust
• Ownership - Konsep dalam Rust yang mengatur bagaimana memori dikelola dan dibebaskan.
• Borrowing dan References - Cara Rust mengizinkan akses ke data tanpa perlu mengambil alih kepemilikan data.
• Lifetimes - Anotasi yang memberitahu Rust berapa lama suatu referensi dapat digunakan.
Penutup And the last! Jadi, setiap bahasa pemrograman memiliki istilah dan konsep yang unik, dan memahami istilah-istilah ini sangat penting untuk menjadi pengembang yang efektif dalam bahasa tersebut saja. Dalam keseluruhan pandangan tentang bahasa pemrograman yang mendukung pengembangan aplikasi di MacOS, terdapat beragam opsi yang memungkinkan para pengembang untuk mengekspresikan kreativitas dan memenuhi kebutuhan proyek mereka. Mulai dari Swift, bahasa yang dirancang oleh Apple sendiri, yang menghadirkan performa tinggi dan sintaksis yang bersih, hingga bahasa yang mapan seperti Objective-C yang masih digunakan dalam proyek-proyek bersejarah.
Lalu ada C++ yang menawarkan kekuatan dalam mengelola perangkat keras dan performa, sedangkan Python menghadirkan fleksibilitas dalam pengembangan aplikasi dengan kode yang lebih mudah dibaca. Java, meskipun lebih terkenal dalam pengembangan Android, juga berfungsi sebagai bahasa yang dapat menciptakan aplikasi lintas platform. Bahasa lain seperti Ruby dan JavaScript dengan Electron memberikan opsi untuk mengembangkan aplikasi MacOS dengan antarmuka modern dan pengalaman pengguna yang baik. Go membawa keamanan dan performa dalam ekosistem MacOS, sementara bahasa seperti Bash dan Rust memberikan alat untuk otomatisasi sistem dan pengembangan perangkat lunak yang lebih aman. Dengan menggabungkan pengetahuan tentang bahasa-bahasa ini, pengembang dapat membuat keputusan yang bijak dalam memilih bahasa yang sesuai dengan tujuan dan kebutuhan aplikasi mereka di dalam lingkungan MacOS yang dinamis. See you!
Source: https://www.elmobsub.com/2023/08/macos-coding-language.html
#electromobile#servicemacbooksurabaya#serviceiphonesurabaya#serviceipadsurabaya#serviceapplesurabaya
0 notes
Text
Into the Extreme - Fold-Expressions
Hi #cpp lovers!
template auto func(Args... args) { return (args || ... );
std::cout << func("str");
Does it compile? What will be the output?
Answers in the article :)
Fold expressions exist in C++ since C++17 and significantly affect how we treat variadic templates. Back in the day, I wrote about fold-expressions as part of the metaprogramming series, but today we will explore the extreme cases of fold-expression usages.
An important disclaimer before we start: In this article, code examples show variadic template usages with arguments passed by value,…
View On WordPress
0 notes
Text
Little guys don't have turing-complete template metaprogramming.
You would not believe the lengths I will go to avoid using C++, including for things that are explicitly supposed to be done in C++
1K notes
·
View notes
Link
1 note
·
View note
Text
C++ for those who asked
Long Post Is Long, so there's a readmore here
I have never programmed before and I want to start with C++
You are possibly an idiot, but go ahead. You'll want Microsoft Visual Studio Community Edition as your programming environment. Once that is installed (During install, remember to ask for the C++ component), start your actual learning at: LearnCpp.
I have programmed before and I have reason to learn C++
Start at "A Tour of C++" by Bjarne Stroustrup, out in third edition as of September 2022.
I would recommend watching Louis Brandy's talk "Curiously Recurring Bugs at Facebook" which doesn't teach you C++ but rather reveals something about what kind of language C++ is, lets you check the Vibe.
And what's next?
Probably still good to read through LearnCpp.
Scott Meyers wrote some good books:
Effective C++ 3rd Edition
Effective STL
More Effective C++
Effective Modern C++
Read in that order. "Effective Modern C++" expands and does not replace "Effective C++"
You should also familiarize yourself with the existence of the Core Guidelines - you're probably not going to sit down and read them end-to-end (...yet) but it's good to know they exist.
Do you know other good books
Yes but... good for what? It's hard to give generic advice here - what are you getting into?
Do you know other good conference talks?
Well define "good" right? But I have a bunch that are interesting, does that count?
Kate Gregory is good at everything:
Simplicity, Not Just For Beginners - General coding principles rather than C++
What Do We Mean When We Say Nothing At All? - What are the defaults, and are they good? (No)
Naming is Hard: Let's Do Better
Other talks
Carl Cook: "When a Microsecond is an Eternity: High Performance Trading Systems in C++"
I want to learn Template Metaprogramming
No you don't
Yes I do
No you don't. You maybe want to solve some kinds of problems that are, from a performance perspective, best solved with template metaprogramming, but you don't "want to learn template metaprogramming" because you are not a fool.
If you have TMP problems I feel bad for you son, I got 99 problems but untestable, undebuggable compile-time conditional code generation ain't one.
Still, if you insist: "Back to Basics: Templates in C++" by Nicolai Josuttis gets you template programming, which lays down the foundation for metaprogramming. You go where I will not follow.
I need to leave for a job interview, post will be expanded later.
26 notes
·
View notes
Text
Programming Gem: Separate means of iteration
I’ve started working on my secret programming project in earnest, which I’ll reveal in full once I have the basics working.
My main philosophy of programming is that if you have an idea in your head, then good programming means putting that idea down in code as is, without having to compromise the idea just to please the particularities of whatever language you're using. You can imagine my thrill when I realized that - by pure coincidence - the D Programming Language happened to share this exact philosophy.
And it shows. Looking through their standard library feels a bit like a child feels like looking around in a candy store. There's a library facility for just about any common programming task, such as automatically generating classes (yes, classes) that automatically implement the abstract methods of an abstract class for your unit testing pleasure, or wrapping an existing type in a class that behaves exactly like the original type but has ADA-like strict typing.
Hacker types who are fans of low-level programming are not left out either with library features that facilitate bit-twiddling such as Bit Fields or using the unused bits of a size-aligned pointer to store data.
I could spend another hundred paragraphs gushing about the language, I haven't even mentioned its language-level unit testing and documentation features, contract programming or scope-level imports. The main focus of this post will be a specific language feature - that is the customizability of the foreach language construct.
In my project I found it necessary to iterate over two ranges and match the element in one range with an element from the other range that is structurally in the same place. This is not always the same thing as iterating on both ranges and matching their current elements - if you're walking two binary trees for example, it's extremely plausible that on the third iteration one tree will be on the right child of the root while the other tree will be on the left child of the left child of the root. This is on the same iteration, but not in the same place structurally. As such, it is necessary for one range to "lead" and the other to follow its exact motions. I use the most naive and inefficient implementation for now - I assume that both ranges have an index which stores a means of getting to the same place structurally, relative to a root element. The resulting code looked something like this:
MatchData matchData; foreach(const index, const ref leaderElement ; leaderRange) { ref FollowerType followerElement; try { // Try to find the element that is in the same structural place in the follower range followerElement = followerRange[index]; } catch (RangeException e) { static if (skipInvalidPairs) { continue; } else { followerElement = null; } } bool hasMatch = leaderElement.Match(followerElement, matchData); if (!hasMatch) { return Nullable!MatchData.init; // return null } } return Nullable!MatchData(matchData);
There are a few unmentioned D-isms here such as static if (which is basically a compile-time if a-la conditional compilation), and Nullable, which basically takes a value type and augments it with the ability to have a null value (which we use when no match occurs).
But look at it! Almost three quarters of the loop body have nothing to do with the actual work being done - it's just bookkeeping and code dealing with loop control! Going back to our basic philosophy of programming, good programming means putting down an idea in code in the same form as it exists in your head. In this case, it's roughly "Iterate over the structurally matching elements of two ranges and match those elements to each other".
Constructs like the original for loop facilitated this by at least taking the loop control code out of the code that did the actual work, and the foreach construct improved on this by abstracting away the means of iteration compeletely, and we only need to specify the range over which we wish to iterate. The obvious solution, then, would be to create a custom range to iterate over only the structurally matching elements of the two arrays (or a null in the follower element, depending on settings). The problem is that such a range would presumably iterate over pairs (or two-tuples) of matching elements, and we would have to spend time retrieving the first and second elements of those pairs, which is more bookkeeping code that we shouldn't have to do, even if it's massively less than our original monstrosity, I wanted more. I wanted zero bookkeeping in the code that does the actual work.
Thankfully, D is a programming language that I would describe as free-spirited. It doesn't (for the most part) arbitrarily limit your use of its constructs, which is what makes it massively powerful. It allows you to do things like importing things in a certain scope, or using all of D's own language constructs to generate code via string mixins, but the possibilities don't end there. You may have noticed in the above code that D supports specifying an index variable as well as the iteration variable, which is an expected feature of any modern programming language. The caviat is that D allows you to overload this functionality, so that the foreach iteration can be whatever you like, and so can the two variables you specify. You can even overload over the number (up to two) and type of loop variables, so that different combinations yield different iterations. The details of how this can be done is detailed in this chapter of Ali Çehreli's excellent book Programming in D.
Here, I will only show my use of this feature. Therefore this programming gem is not so much my idea as it is a demonstration of one of D's many amazing features. What I wanted to do is define a class that takes two ranges and provides a foreach iteration for elements that are in the same place structurally in both ranges. I also wanted to be able to specify whether to present nonmatching elements as null or skip them altogether. I could also add additional options such as ending the iteration or throwing an exception when such a mismatch is encountered, but for simplicity I will stick with the skip/don't skip solution. With this feature implemented, we have truly reached (or almost) the ideal iteration where we only need to specify the options of our iteration, and then merely write code that does the actual work, with zero bookkeeping code.
Well, without further ado, here is the implementation of such a range:
struct TogetherRange(LeaderRange,FollowerRange, bool SkipInvalidPairs = false) if (isInputRange!LeaderRange && isInputRange!FollowerRange) { public: alias LeaderValue = ElementType!LeaderRange; alias FollowerValue = ElementType!FollowerRange; this(ref LeaderRange l,ref FollowerRange f) { m_leaderRange = l; m_followerRange = f; } int opApply(int delegate(ref LeaderValue,ref FollowerValue) loopBody) const { int result = 0; foreach(const index, ref LeaderValue leader ; m_leaderRange) { ref FollowerValue follower; try { follower = m_followerRange[index]; } catch (RangeException e) { static if (skipInvalidPairs) { continue; } else { follower = null; } } result = loopBody(leader, follower); } return result; } private: LeaderRange m_leaderRange; FollowerRange m_followerRange; } template Together(LeaderRange,FollowerRange, bool SkipInvalidPairs = false) if (isInputRange!LeaderRange && isInputRange!FollowerRange) { alias RangeT = TogetherRange!(LeaderRange,FollowerRange,SkipInvalidPairs); RangeT Together(ref LeaderRange l, ref FollowerRange f) { return RangeT(l,f); } }
For brevity this class is missing its obviously needed range iterator methods, which need to be generated based on what methods both ranges support, which is too much irrelevant code to what this post is really about. The opApply function takes a delegate which is the loop body (similar to std::for_each of C++ fame) and surrounds that with its own code for the actual iteration part. You can see the beauty of seperation of concerns here - this whole opApply function is merely a means to separate out the bookkeeping code from the loop body that does the actual work. Our loop handling code is now nicely and completely sepearated from code that does the actual work, enablind us to merely request the proper means of iteration and then do our work undisturbed. The final foreach loop that uses the above class looks like this:
MatchData matchData; foreach(const ref LeaderType leaderValue, const ref FollowerType followerValue ; Together(leaderRange, followerRange)) { bool hasMatch = leaderValue.Match(followerValue, matchData); if (!hasMatch) { return Nullable!MatchData.init; } } return Nullable!MatchData(matchData);
This code now only concerns itself with specifying the means of iteration and then doing the actual work. As a result, our code is much cleaner and easier to understand. The loop body in the foreach above gets turned into a delegate and passed to the opApply method of our TogetherRange class. Of course we neglect to do a few things, such as handling the case then followerValue is null, but whether we should do that in the loop body or not is the same as a simple question - does a structural mismatch that would lead to such a case affect the loop control, or does it affect how the work is done? If it affects loop control, then it's better delegated to the range via an option (skipping mismatched elements or bailing out of the loop on a structural mismatch is such a decision). On the other hand if it merely affects how the matching is done (against a nonexistent element), then it is best left to the Match function. One could argue that even returning on a failed match is something best left to another part of the code - for example the matching rule could be extended by an option that tells it how to handle matching against nonexistent elements, or it could even be tasked with handling match failures altogether (such as making any matching rule optional - so that only the matching for that single element is discarded, rather than the entire collection of match elements).
But I'm just rambling now, and there's lots of more basic work to be done before a coherent system arises from this little project of mine. However, my hope is that once a basic version is up and running, it will be able to do some awesome things.
#programming#D#C++#D programming#pattern matching#abstraction#template metaprogramming#templates#programming gem
2 notes
·
View notes
Text
macro expansion slows compilation.
It generates a lot of code, much of it redundant, and needs a good linker to eliminate duplicate copies. The individual specializations may be efficient but the program as a whole can suffer due to poor use of the instruction cache. I have heard of simple libraries having text segments shrink from megabytes to tens of kilobytes by revising or eliminating the use of templates.
—Russ Cox
2 notes
·
View notes