టెంప్లేట్లు & Generic Programming
ఆధునిక సాఫ్ట్వేర్ అభివృద్ధిలో ఒకే లాజిక్ను పూర్ణాంకాలు (int), దశాంశాలు (double), అక్షరాలు (char) లేదా కస్టమ్ ఆబ్జెక్టుల కోసం వేర్వేరుగా పదే పదే రాయడం అనేది సమయం మరియు మానవ శ్రమను వృధా చేయడమే. ఈ సమస్యకు C++ అందించిన అద్భుతమైన మరియు అసమానమైన పరిష్కారమే టెంప్లేట్లు (Templates) & జెనరిక్ ప్రోగ్రామింగ్ (Generic Programming).
ఇతర ప్రోగ్రామింగ్ భాషల్లో (Java Generics లేదా C# వంటివి) జెనరిక్స్ రన్టైమ్లో బాక్సింగ్/అన్బాక్సింగ్ మరియు టైప్-ఎరేజర్ (Type Erasure) ద్వారా పనిచేసి పనితీరును తగ్గిస్తాయి. కానీ C++ లో టెంప్లేట్లు కంపైల్-టైమ్ కోడ్ జనరేషన్ (Compile-time Monomorphization) ద్వారా పనిచేస్తాయి! ఫలితంగా సున్నా రన్టైమ్ ఓవర్హెడ్ (Zero Runtime Overhead) తో చేతితో రాసిన మెషిన్ అసెంబ్లీ కోడ్ అంతే వేగంతో అమలవుతాయి. అంతేకాకుండా Modern C++20 లో ప్రవేశపెట్టిన విప్లవాత్మకమైన Concepts & Constraints టెంప్లేట్ ప్రోగ్రామింగ్ను మరింత సురక్షితంగా మరియు సులభంగా మార్చాయి.
ఈ సమగ్ర మాస్టర్క్లాస్లో మనం Function & Class Templates, Non-type Template Parameters (NTTP), Template Specialization, Variadic Templates (C++11/C++17 Fold Expressions), C++20 Concepts & requires నిబంధనలు, మరియు పూర్తి స్థాయి "Enterprise High-Performance Generic Lock-Free Ring Buffer Engine" ప్రాజెక్ట్ను ప్రత్యక్షంగా నిర్మించి నేర్చుకుందాం!
1 జెనరిక్ ప్రోగ్రామింగ్ అంటే ఏమిటి? (Code Generation Automation)
జెనరిక్ ప్రోగ్రామింగ్ (Generic Programming) అంటే ఏమిటి? నిర్దిష్టమైన డేటా టైప్లతో (int, string, double) సంబంధం లేకుండా, ఒక సాధారణ బ్లూప్రింట్ (Type-Agnostic Algorithm) రాసి, ఏ డేటా టైప్కైనా సరిపోయేలా కోడ్ను రూపొందించే పద్ధతిని జెనరిక్ ప్రోగ్రామింగ్ అంటారు.
C++ లో ఈ జెనరిక్ ఫిలాసఫీని సాధ్యం చేసే సాధనాలే టెంప్లేట్లు (Templates).
టెంప్లేట్లు ఎలా పనిచేస్తాయి?
మీరు టెంప్లేట్ రాసినప్పుడు కంపైలర్ నేరుగా మెషిన్ కోడ్ను సృష్టించదు! మీరు ప్రోగ్రామ్లో ఆ టెంప్లేట్ను int తో పిలిస్తే, కంపైలర్ వెనుక వైపు int వెర్షన్ ఫంక్షన్ను ఆటోమేటిక్గా టైప్ చేస్తుంది; మీరు double తో పిలిస్తే double వెర్షన్ను రూపొందిస్తుంది. ఈ ప్రక్రియను Template Instantiation అంటారు.
2 ఫంక్షన్ టెంప్లేట్లు (Function Templates: template )
రెండు విలువలలో ఏది పెద్దదో కనుగొనడానికి సాధారణంగా మనం int max(int, int), double max(double, double) అని విడివిడిగా రాస్తుంటాం. కానీ ఫంక్షన్ టెంప్లేట్తో ఒక్కటే సరిపోతుంది:
template <typename T>
T getMaximum(T a, T b) {
return (a > b) ? a : b;
}
ఇక్కడ typename మరియు class కీవర్డ్లు రెండూ సరిగ్గా ఒకే విధంగా పనిచేస్తాయి (రెంటిలో దేనినైనా వాడవచ్చు).
#include <iostream>
#include <string>
// జెనరిక్ ఫంక్షన్ టెంప్లేట్
template <typename T>
T findMax(T a, T b) {
return (a > b) ? a : b;
}
// బహుళ విభిన్న టైప్ల టెంప్లేట్ (Multi-type Template)
template <typename T, typename U>
void printPair(T first, U second) {
std::cout << "జత: [" << first << ", " << second << "]\n";
}
int main() {
std::cout << "పూర్ణాంకాల గరిష్టం (int): " << findMax(25, 42) << "\n";
std::cout << "దశాంశాల గరిష్టం (double): " << findMax(99.45, 12.30) << "\n";
std::cout << "అక్షరాల గరిష్టం (string): " << findMax(std::string("Hyderabad"), std::string("Bengaluru")) << "\n";
std::cout << "\nబహుళ టైప్ జతలు:\n";
printPair("RollNo", 101);
printPair(3.14159, "PI Value");
return 0;
}
3 క్లాస్ టెంప్లేట్లు (Class Templates: Generic Containers)
ఏ డేటా టైప్నైనా భద్రపరచగల జెనరిక్ డేటా స్ట్రక్చర్లను (ఉదాహరణకు std::vector<T>, std::stack<T>) రూపొందించడానికి క్లాస్ టెంప్లేట్లు ఉపయోగపడతాయి.
#include <iostream>
#include <string>
// జెనరిక్ క్లాస్ టెంప్లేట్
template <typename T>
class SecureBox {
private:
T content;
public:
SecureBox(T val) : content(val) {}
void setContent(T val) { content = val; }
T getContent() const { return content; }
void inspect() const {
std::cout << " 📦 [SecureBox] డేటా విలువ: " << content
<< " (సైజ్: " << sizeof(content) << " Bytes)\n";
}
};
int main() {
SecureBox<int> intBox(5000);
SecureBox<double> dblBox(999.85);
SecureBox<std::string> strBox("Secret-Bank-Vault-Token");
intBox.inspect();
dblBox.inspect();
strBox.inspect();
return 0;
}
4 Non-Type Template Parameters (NTTP)
టెంప్లేట్లలో కేవలం డేటా టైప్లనే కాకుండా, పూర్ణాంక సంఖ్యలను (Integers, Pointers, Enums) కూడా టెంప్లేట్ పారామీటర్గా పాస్ చేయవచ్చు. దీనినే Non-Type Template Parameter (NTTP) అంటారు.
ఉపయోగం: కంపైల్-టైమ్లోనే ఫిక్స్డ్ సైజ్ కలిగిన మెమరీ బఫర్లను సృష్టించి, హీప్ మెమరీ అలొకేషన్ ఓవర్హెడ్ను పూర్తిగా నివారించవచ్చు (ఉదాహరణకు std::array<T, N>).
#include <iostream>
// T అనేది డేటా టైప్, Size అనేది NTTP సంఖ్య!
template <typename T, size_t Size>
class StaticStack {
private:
T buffer[Size];
size_t count = 0;
public:
bool push(const T& val) {
if (count >= Size) return false;
buffer[count++] = val;
return true;
}
T pop() {
if (count == 0) throw std::underflow_error("స్టాక్ ఖాళీగా ఉంది!");
return buffer[--count];
}
size_t capacity() const { return Size; }
size_t size() const { return count; }
};
int main() {
// 5 ఎలిమెంట్ల ఫిక్స్డ్ సైజ్ స్టాక్ (హీప్ అలొకేషన్ లేదు - 100% స్టాక్ మెమరీ!)
StaticStack<int, 5> fastStack;
fastStack.push(10);
fastStack.push(20);
fastStack.push(30);
std::cout << "స్టాక్ సామర్థ్యం: " << fastStack.capacity() << " | ఎలిమెంట్లు: " << fastStack.size() << "\n";
std::cout << "పాప్ చేసిన విలువ: " << fastStack.pop() << "\n";
return 0;
}
5 టెంప్లేట్ స్పెషలైజేషన్ (Full & Partial Specialization)
సాధారణ జెనరిక్ నియమం అన్ని టైప్లకూ సరిపోయినప్పటికీ, ఏదైనా ఒక నిర్దిష్ట డేటా టైప్ కోసం ప్రత్యేకమైన ఆప్టిమైజ్డ్ లాజిక్ అవసరమైనప్పుడు టెంప్లేట్ స్పెషలైజేషన్ (Template Specialization) ను ఉపయోగిస్తాం.
- Full Specialization: టెంప్లేట్ పారామీటర్లను పూర్తిగా ఒక నిర్దిష్ట టైప్కు కట్టబెట్టడం:
template <> class MyBox<bool> { ... }; - Partial Specialization: పాయింటర్ల కోసం లేదా పాక్షిక టైప్ల కోసం స్పెషలైజ్ చేయడం:
template <typename T> class MyBox<T*> { ... };
#include <iostream>
// 1. సాధారణ జెనరిక్ టెంప్లేట్
template <typename T>
class Formatter {
public:
static void print(T val) {
std::cout << " [సాధారణ ఫార్మాట్]: " << val << "\n";
}
};
// 2. Full Specialization for bool (0/1 కాకుండా True/False ప్రింట్ కొరకు)
template <>
class Formatter<bool> {
public:
static void print(bool val) {
std::cout << " [బూలియన్ స్పెషలైజ్డ్ ఫార్మాట్]: " << (val ? "TRUE (నిజం)" : "FALSE (అబద్ధం)") << "\n";
}
};
int main() {
Formatter<int>::print(100);
Formatter<double>::print(3.14);
Formatter<bool>::print(true); // స్పెషలైజ్డ్ వెర్షన్ అమలవుతుంది!
return 0;
}
6 డీఫాల్ట్ టెంప్లేట్ ఆర్గుమెంట్లు (Default Template Arguments)
ఒక టెంప్లేట్ను ఉపయోగించేటప్పుడు ప్రోగ్రామర్ టైప్ను స్పష్టంగా చెప్పకపోతే కంపైలర్ డిఫాల్ట్గా ఒక టైప్ను తీసుకోవడానికి మనం డీఫాల్ట్ ఆర్గుమెంట్లను ఇవ్వవచ్చు:
template <typename T = double, size_t Capacity = 64>
class RingBuffer { ... };
ఇప్పుడు RingBuffer<> buf; అని రాస్తే అది ఆటోమేటిక్గా double మరియు 64 సైజుతో ఇన్స్టాన్షియేట్ అవుతుంది.
7 వేరియాడిక్ టెంప్లేట్లు & C++17 Fold Expressions
వేరియాడిక్ టెంప్లేట్లు (Variadic Templates - C++11): ఎన్ని ఆర్గుమెంట్లనైనా (0, 1, 5, లేదా 100) స్వీకరించగల జెనరిక్ ఫంక్షన్లను రూపొందించడానికి typename... Args (Parameter Pack) ను ఉపయోగిస్తాం.
Modern C++17 Fold Expressions: పాత C++11 లో పారామీటర్ ప్యాక్ను లెక్కించడానికి రికర్సివ్ ఫంక్షన్లు రాయాల్సి వచ్చేది. కానీ C++17 లో (args + ...) అనే ఒక్క చిన్న సమీకరణంతో మొత్తం ప్యాక్ను అద్భుతంగా సమ్మేషన్ చేయవచ్చు!
#include <iostream>
// C++17 Fold Expression ద్వారా ఎన్ని సంఖ్యలనైనా ఒక్క లైన్లో కూడటం!
template <typename... Args>
auto sumAll(Args... args) {
return (args + ...); // Unary Right Fold: (a1 + (a2 + (a3 + ...)))
}
int main() {
std::cout << "3 సంఖ్యల మొత్తం: " << sumAll(10, 20, 30) << "\n";
std::cout << "5 సంఖ్యల మొత్తం: " << sumAll(1.5, 2.5, 3.0, 4.0, 5.0) << "\n";
std::cout << "స్ట్రింగ్స్ కలయిక: " << sumAll(std::string("C++20 "), std::string("Fold "), std::string("Magic!")) << "\n";
return 0;
}
8 కంపైల్-టైమ్ ప్రోగ్రామింగ్ & if constexpr (C++17)
రన్టైమ్లో if-else కండిషన్లను చెక్ చేస్తే ప్రోగ్రామ్ స్పీడ్ తగ్గుతుంది. కానీ if constexpr ద్వారా కంపైల్-టైమ్లోనే కండిషన్ తనిఖీ చేయబడి, తప్పుడు బ్రాంచ్ కోడ్ అసలు బైనరీ ఫైల్లోకే రాకుండా పూర్తిగా తొలగించబడుతుంది (Dead Code Elimination)!
#include <iostream>
#include <type_traits>
template <typename T>
void processData(T val) {
if constexpr (std::is_pointer_v<T>) {
std::cout << " పాయింటర్ డేటా డీరిఫరెన్స్: " << *val << "\n";
} else {
std::cout << " డైరెక్ట్ వాల్యూ డేటా: " << val << "\n";
}
}
int main() {
int num = 42;
processData(num); // else బ్రాంచ్ మాత్రమే కంపైల్ అవుతుంది!
processData(&num); // if బ్రాంచ్ మాత్రమే కంపైల్ అవుతుంది!
return 0;
}
9 Modern C++20 విప్లవం: Concepts & Constraints (requires)
C++ చరిత్రలో గత 30 ఏళ్లుగా టెంప్లేట్ ప్రోగ్రామర్లను వేధించిన అతిపెద్ద సమస్య: క్రిప్టిక్ ఎర్రర్ మెసేజ్లు (Cryptic Compiler Errors). ఒక టెంప్లేట్ ఫంక్షన్కు తప్పుడు టైప్ పాస్ చేస్తే 500 లైన్ల అర్థం కాని ఎర్రర్ వచ్చేది!
ఈ సమస్యకు Modern C++20 లో లభించిన విప్లవాత్మక పరిష్కారమే Concepts & Constraints.
#include <iostream>
#include <concepts>
// C++20 Standard Concept: std::integral (పూర్ణాంకాలు మాత్రమే!)
template <std::integral T>
T computeModulo(T a, T b) {
return a % b;
}
// Custom Concept: నంబర్లు (int లేదా float) మాత్రమే
template <typename T>
concept Numeric = std::integral<T> || std::floating_point<T>;
template <Numeric T>
T average(T a, T b) {
return (a + b) / 2;
}
int main() {
std::cout << "Modulo (15 % 4): " << computeModulo(15, 4) << "\n";
// computeModulo(15.5, 4.2); // ❌ కంపైలర్ క్లీన్ ఎర్రర్: Constraints not satisfied!
std::cout << "Average: " << average(10.5, 20.5) << "\n";
return 0;
}
10 టెంప్లేట్స్ హెడర్-ఓన్లీ స్వభావం & Code Bloat నివారణ
హెడర్-ఓన్లీ రూల్ (The Header-Only Rule):
సాధారణ C++ ఫంక్షన్లలా కాకుండా, టెంప్లేట్ల యొక్క పూర్తి డిక్లరేషన్ మరియు ఇంప్లిమెంటేషన్ను తప్పనిసరిగా హెడర్ ఫైల్స్ (.hpp / .h) లోనే ఉంచాలి! ఎందుకంటే వేరే ఫైల్ టెంప్లేట్ను పిలిచినప్పుడు కంపైలర్కు ఆ టైప్ కొరకు కొత్త కోడ్ను సృష్టించడానికి పూర్తి టెంప్లేట్ బాడీ కంటికి కనిపించాలి.
కోడ్ బ్లోట్ (Code Bloat): టెంప్లేట్లను 100 వేర్వేరు టైప్లతో వాడితే బైనరీ ఎగ్జిక్యూటబుల్ సైజు పెరుగుతుంది. దీనిని నివారించడానికి కామన్ లాజిక్ను నాన్-టెంప్లేట్ బేస్ క్లాస్లో ఉంచడం ప్రొఫెషనల్ పద్ధతి.
11 సాధారణ టెంప్లేట్ తప్పులు & డీబగ్గింగ్ గైడ్
-
Dependent Names లో
typenameమర్చిపోవడం: టెంప్లేట్ లోపల వేరొక టైప్ను యాక్సెస్ చేసేటప్పుడు (ఉదా:T::iterator) కంపైలర్కు అది వేరియబుల్ కాదని చెప్పడానికిtypename T::iteratorఅని రాయాలి. -
టెంప్లేట్ డెఫినిషన్ను
.cppలో దాచిపెట్టడం: దీనివల్ల లింకర్ ఎర్రర్ (Undefined Reference) వస్తుంది.
12 రియల్-వరల్డ్ ప్రాజెక్ట్: Enterprise High-Performance Generic Lock-Free Ring Buffer Engine
నిజ జీవితంలో హై-స్పీడ్ ఆడియో ఇంజిన్లు (FL Studio, ProTools), ఆటోమోటివ్ CAN-Bus నెట్వర్క్లు మరియు హై-ఫ్రీక్వెన్సీ ట్రేడింగ్ సిస్టమ్స్ సెకనుకు లక్షలాది మెసేజ్లను జీరో హీప్ అలొకేషన్ మరియు జీరో లాక్లతో పాస్ చేయడానికి రింగ్ బఫర్ (Circular Queue) ను ఉపయోగిస్తాయి.
ఈ సమగ్ర ప్రాజెక్ట్లో మనం C++20 Concepts, Non-type Template Parameters, మరియు కంపైల్-టైమ్ సైజ్ నిర్ధారణతో కూడిన ఒక ఎంటర్ప్రైజ్ జెనరిక్ రింగ్ బఫర్ ఇంజిన్ ను నిర్మిస్తున్నాం:
#include <iostream>
#include <string>
#include <type_traits>
#include <concepts>
#include <optional>
// C++20 Concept: కాపీ కన్స్ట్రక్ట్ చేయగల టైప్లకు మాత్రమే అనుమతి!
template <typename T>
concept Bufferable = std::is_copy_constructible_v<T>;
// జెనరిక్ రింగ్ బఫర్ క్లాస్ టెంప్లేట్ విత్ NTTP Capacity
template <Bufferable T, size_t Capacity>
class RingBuffer {
static_assert(Capacity > 0, "❌ బఫర్ కెపాసిటీ ఖచ్చితంగా 0 కంటే ఎక్కువ ఉండాలి!");
private:
T buffer[Capacity]; // ఫిక్స్డ్ సైజ్ స్టాక్ బఫర్ (జీరో హీప్ ఓవర్హెడ్!)
size_t head = 0;
size_t tail = 0;
size_t currentSize = 0;
public:
RingBuffer() = default;
bool enqueue(const T& item) {
if (currentSize == Capacity) {
return false; // బఫర్ ఫుల్!
}
buffer[tail] = item;
tail = (tail + 1) % Capacity;
currentSize++;
return true;
}
std::optional<T> dequeue() {
if (currentSize == 0) {
return std::nullopt; // బఫర్ ఖాళీ!
}
T item = buffer[head];
head = (head + 1) % Capacity;
currentSize--;
return item;
}
size_t size() const { return currentSize; }
size_t maxCapacity() const { return Capacity; }
bool isEmpty() const { return currentSize == 0; }
bool isFull() const { return currentSize == Capacity; }
};
struct TelemetryLog {
int sensorId;
double reading;
};
int main() {
std::cout << "=======================================================================\n";
std::cout << "🔄 [ENTERPRISE GENERIC RING BUFFER & CIRCULAR QUEUE ENGINE]\n";
std::cout << "=======================================================================\n";
// 1. పూర్ణాంకాల (int) రింగ్ బఫర్ (సామర్థ్యం: 4)
RingBuffer<int, 4> intQueue;
std::cout << "\n[టెస్ట్ 1: పూర్ణాంకాల రింగ్ బఫర్ (Capacity: 4)]:\n";
intQueue.enqueue(101);
intQueue.enqueue(102);
intQueue.enqueue(103);
intQueue.enqueue(104);
if (!intQueue.enqueue(105)) {
std::cout << " ⚠️ బఫర్ నిండిపోయింది (105 డ్రాప్ చేయబడింది!)\n";
}
while (!intQueue.isEmpty()) {
std::cout << " రీడ్ చేసిన ఐటెమ్: " << *intQueue.dequeue() << "\n";
}
// 2. కస్టమ్ స్ట్రక్చర్ (TelemetryLog) రింగ్ బఫర్
RingBuffer<TelemetryLog, 3> telemetryQueue;
std::cout << "\n[టెస్ట్ 2: జెనరిక్ టెలిమెట్రీ సెన్సార్ స్ట్రీమ్]:\n";
telemetryQueue.enqueue({0xAA1, 38.4});
telemetryQueue.enqueue({0xAA2, 42.1});
while (auto item = telemetryQueue.dequeue()) {
std::cout << " 📡 సెన్సార్ ID: 0x" << std::hex << item->sensorId
<< std::dec << " | ఉష్ణోగ్రత: " << item->reading << " °C\n";
}
std::cout << "\n=======================================================================\n";
std::cout << "✅ C++20 Concepts తో జెనరిక్ రింగ్ బఫర్ ఎగ్జిక్యూషన్ విజయవంతమైంది!\n";
std::cout << "=======================================================================\n";
return 0;
}
13 సారాంశం & ఇంటరాక్టివ్ క్విజ్ (Summary & Self-Check Quizzes)
📌 ఈ అధ్యాయంలో నేర్చుకున్న ప్రధాన అంశాలు:
- Generic Programming: డేటా టైప్తో సంబంధం లేకుండా టైప్-ఇండిపెండెంట్ కోడ్ రాసే శక్తి.
- Template Instantiation: కంపైలర్ మనం వాడే ప్రతి టైప్ కొరకు కంపైల్-టైమ్లోనే అసలు మెషిన్ కోడ్ను ఉచితంగా సృష్టిస్తుంది (Zero Runtime Overhead).
- NTTP (Non-Type Template Parameters): సైజులు, సంఖ్యలను టెంప్లేట్ ఆర్గుమెంట్లుగా పాస్ చేసి ఫిక్స్డ్ సైజ్ బఫర్లను నిర్మించడం.
- Template Specialization: నిర్దిష్ట డేటా టైప్ల కొరకు (ఉదా:
bool) ప్రత్యేకమైన ఆప్టిమైజ్డ్ లాజిక్ అందించడం. - Fold Expressions (C++17): వేరియాడిక్ పారామీటర్ ప్యాక్ను రికర్షన్ లేకుండా
(args + ...)తో సింపుల్గా ఎవాల్యుయేట్ చేయడం. - if constexpr (C++17): కంపైల్-టైమ్ బ్రాంచింగ్ ద్వారా అనవసరమైన కోడ్ బ్రాంచ్ను పూర్తిగా తొలగించడం.
- Concepts & Constraints (C++20): టెంప్లేట్ టైప్లపై కచ్చితమైన నిబంధనలు విధించి క్రిప్టిక్ ఎర్రర్లను రూపుమాపడం.
- Header-Only Rule: టెంప్లేట్ ఫంక్షన్ల పూర్తి కోడ్ను ఎల్లప్పుడూ హెడర్ ఫైళ్లలోనే ఉంచాలి.
🧠 మీ అవగాహనను పరీక్షించుకోండి (5 Interactive Quizzes):
ప్రశ్న 1: C++ టెంప్లేట్లు ఇతర భాషల జెనరిక్స్ (Java Generics) కంటే ఎందుకు మెరుపు వేగంతో పనిచేస్తాయి?
వివరణ: Java లో రన్టైమ్లో ఆబ్జెక్ట్ కాస్టింగ్ మరియు బాక్సింగ్ జరుగుతుంది. C++ లో కంపైలర్ ప్రతి టైప్కు విడివిడిగా అత్యుత్తమ అసెంబ్లీ మెషిన్ కోడ్ను ముందే ఉత్పత్తి చేస్తుంది, ఫలితంగా రన్టైమ్ పెనాల్టీ సున్నా.
ప్రశ్న 2: టెంప్లేట్ డెఫినిషన్లను .cpp ఫైల్లో కాకుండా హెడర్ ఫైల్స్ (.hpp) లోనే ఎందుకు రాయాలి?
వివరణ: వేరొక ట్రాన్స్లేషన్ యూనిట్ లో టెంప్లేట్ను కాల్ చేసినప్పుడు బాడీ
.cpp లో దాగి ఉంటే కంపైలర్ కోడ్ జనింపజేయలేదు; ఫలితంగా లింకింగ్ సమయంలో undefined reference ఎర్రర్ వస్తుంది.
ప్రశ్న 3: Non-Type Template Parameter (NTTP) అంటే ఏమిటి?
వివరణ: ఉదాహరణకు
template <typename T, size_t N> class Array లో N అనేది NTTP. దీనివల్ల కంపైల్-టైమ్లోనే ఫిక్స్డ్ సైజ్ కేటాయించబడి మెమరీ వేగం పెరుగుతుంది.
ప్రశ్న 4: Modern C++20 లో Concepts ప్రవేశపెట్టడానికి గల ప్రధాన కారణం ఏమిటి?
వివరణ: తప్పుడు టైప్ పాస్ చేసినప్పుడు వందల కొద్దీ లైన్ల లోపాలు రాకుండా, కంపైలర్ "Constraints not satisfied" అని స్పష్టమైన సూటి ఎర్రర్ ఇస్తుంది.
ప్రశ్న 5: C++17 లోని if constexpr సాధారణ if కంటే ఎలా భిన్నమైనది?
if constexpr కంపైల్-టైమ్లోనే కండిషన్ను లెక్కించి, తప్పుడు బ్రాంచ్ను అసలు బైనరీ లోకే రాకుండా తొలగిస్తుంది!వివరణ: సాధారణ
if రన్టైమ్లో చెక్ అవుతుంది మరియు రెండు బ్రాంచ్ల కోడ్ బైనరీలో ఉంటుంది. if constexpr లో కంపైలర్ కేవలం సరైన బ్రాంచ్ను మాత్రమే కంపైల్ చేసి మిగిలిన దాన్ని డెడ్ కోడ్గా పారేస్తుంది.
ఈ ప్రాజెక్ట్ను లైవ్గా మన కంపైలర్లో రన్ చేయండి!
ఎటువంటి లోకల్ సెటప్ లేకుండా, బ్రౌజర్లోనే నేరుగా Modern C++ (GCC 13 / C++20) కంపైలర్లో ఈ కోడ్ను ఎగ్జిక్యూట్ చేసి రన్టైమ్ అవుట్పుట్ను తనిఖీ చేయండి.