Writing code to the compiler
Introduction
This post aims to show how c++ compiler codes at run-time.
Starting
Before we start the post, we need to talk about c++ templates.
The C++ templates, the codes which is written at run-time by compiler. We can take advantage of some C++ usefull syntax knowladges as like function overloading, type-independent function or class definitions
Let’s let the compiler write the code
print function
Now, we will code a print function which prints all given arguments to standart output stream. When we code that function, we will use 2 seperate tecnique to implement this function.
First one, subtraction technique:
#include <iostream>
template<typename T>
void print(T x){
std::cout << x << '\n';
}
template<typename T, typename ...Args>
void print(T x, Args ...args){
std::cout << x << ", ";
print(args...);
}
As seen above, we have implemented subtraction technique
using variadic
and T
overloaded functions.
if we use print function as like below,
print(5, 2.3, 4.7f, "hello world", 'c');
Compiler writes the code below,
void print(int, double, float, const char*, char);
void print(double, float, const char*, char);
void print(float, const char*, char);
void print(const char*, char);
void print(char);
Second one, comma operator technique:
Before we apply this technique, we need to mention comma operator. Comma operator gives us the guarantee which is processed arguments until last arguments.
int x = 10, y = 20, z = 30;
(++x, ++y, z = x + y);
std::cout << z; // x = 11, y = 21, z = 33
We can use the technique;
#include <iostream>
template<typename ...Tpacks>
void print(Tpacks ...packs){
int a[]{
(std::cout << packs << ", ", 0)...
};
}
or,
#include <iostream>
#include <initializer_list>
template<typename ...Tpacks>
void print(Tpacks ...packs){
(void)std::initializer_list<int>{
(std::cout << packs << ", ", 0)...
};
}
Now compiler writes code for us as like below,
void print(T1 p1, T2 p2, T3 p3){
(void)std::initializer_list<int>{
(std::cout << p1 << ", " ,0 ),
(std::cout << p2 << ", " ,0 ),
(std::cout << p3 << ", " ,0 ),
};
}
Calculation the expression using templates
Factorial
template<int n>
struct Factorial : Factorial<n - 1>{
const static int value = n * Factorial<n-1>::value;
};
template<>
struct Factorial<1>{
const static int value = 1;
};
#include <iostream>
int main(){
std::cout << Factorial<5>::value << '\n';
constexpr auto i = Factorial<4>::value;
}
Power
template<int base, int power>
struct Power{
const static int value = base * Power<base, power-1>::value;
};
template<int base>
struct Power<base, 1>{
const static int value = base;
};
#include <iostream>
int main(){
std::cout << Power<2,5>::value << '\n';
constexpr auto i { Power<2, 5>::value };
}
Summer
template<typename T>
T summer(T last){
return last;
}
template<typename T, typename ...Args>
T summer(T first, const Args& ...args){
return first + summer(args...);
}
#include <iostream>
#include <string>
int main(){
using namespace std;
std::cout << summer(10, 20, 30) << '\n';
string s1{ "Bur" }, s2{ "ak" };
std::cout << summer(s1, s2, " Büyük"s, "yüksel"s) << '\n';
}
60
burak Büyükyüksel