C++ তে টেমপ্লেট (Templates) একটি গুরুত্বপূর্ণ বৈশিষ্ট্য যা প্রোগ্রামিংয়ে কোড পুনরায় ব্যবহারযোগ্যতা (code reusability) বাড়ায়। টেমপ্লেট এমন এক ধরনের জেনেরিক প্রোগ্রামিং পদ্ধতি যা প্রোগ্রামারদের একাধিক ডেটা টাইপের জন্য একই কোড লিখতে সাহায্য করে। C++ তে দুটি প্রধান ধরনের টেমপ্লেট রয়েছে:
- ফাংশন টেমপ্লেট (Function Templates)
- ক্লাস টেমপ্লেট (Class Templates)
১. ফাংশন টেমপ্লেট
ফাংশন টেমপ্লেট এমন এক ধরনের ফাংশন যা একাধিক ডেটা টাইপের জন্য কাজ করতে পারে। এটি একটি সাধারণ ফর্ম্যাট যা একাধিক টাইপের জন্য একটি একক ফাংশন তৈরি করতে দেয়। যখন ফাংশনটি কল করা হয়, তখন ডেটা টাইপ অনুযায়ী ফাংশন টেমপ্লেটটি সেই ডেটা টাইপে কাজ করে।
ফাংশন টেমপ্লেটের গঠন
template <typename T>
T functionName(T parameter) {
// ফাংশনের কাজ
}template <typename T>: এটি টেমপ্লেটের ঘোষণা।Tএকটি টেমপ্লেট প্যারামিটার যা টাইপকে নির্ধারণ করে।T: এটি একটি জেনেরিক টাইপ যাfunctionNameএ ব্যবহৃত হয়।
উদাহরণ (Function Template)
#include <iostream>
template <typename T>
T add(T a, T b) {
return a + b;
}
int main() {
std::cout << "Sum of integers: " << add(5, 10) << std::endl;
std::cout << "Sum of doubles: " << add(3.14, 2.71) << std::endl;
return 0;
}ব্যাখ্যা:
addফাংশনটি একটি টেমপ্লেট ফাংশন যাTটাইপ প্যারামিটার গ্রহণ করে।- এটি ইন্টিজার এবং ডাবল দুই ধরনের ইনপুট দিয়ে কাজ করতে পারে।
২. ক্লাস টেমপ্লেট
ক্লাস টেমপ্লেট একটি সাধারণ ক্লাস যা একাধিক ডেটা টাইপের জন্য কাজ করতে পারে। ক্লাস টেমপ্লেট ব্যবহার করে প্রোগ্রামাররা একাধিক ডেটা টাইপের জন্য একটি ক্লাস তৈরি করতে পারেন।
ক্লাস টেমপ্লেটের গঠন
template <typename T>
class ClassName {
private:
T data;
public:
ClassName(T data) : data(data) {}
T getData() {
return data;
}
};template <typename T>: এটি ক্লাস টেমপ্লেটের ঘোষণা।T: এটি একটি জেনেরিক টাইপ যা ক্লাসের মধ্যে ব্যবহৃত হয়।
উদাহরণ (Class Template)
#include <iostream>
template <typename T>
class Box {
private:
T value;
public:
Box(T value) : value(value) {}
T getValue() {
return value;
}
};
int main() {
Box<int> intBox(123);
Box<double> doubleBox(3.1415);
std::cout << "Integer value: " << intBox.getValue() << std::endl;
std::cout << "Double value: " << doubleBox.getValue() << std::endl;
return 0;
}ব্যাখ্যা:
Boxক্লাসটি একটি টেমপ্লেট ক্লাস যাTটাইপের ভেরিয়েবল ধারণ করে।- এই ক্লাসটি ইন্টিজার এবং ডাবল ধরনের ভ্যালু নিয়ে কাজ করতে পারে।
একাধিক টেমপ্লেট প্যারামিটার
C++ এ একটি ফাংশন বা ক্লাসে একাধিক টেমপ্লেট প্যারামিটার ব্যবহার করা যায়।
#include <iostream>
template <typename T1, typename T2>
class Pair {
private:
T1 first;
T2 second;
public:
Pair(T1 first, T2 second) : first(first), second(second) {}
void display() {
std::cout << "First: " << first << ", Second: " << second << std::endl;
}
};
int main() {
Pair<int, double> p(1, 3.14);
p.display();
return 0;
}ব্যাখ্যা:
- এখানে
Pairক্লাসটি দুটি টেমপ্লেট প্যারামিটারT1এবংT2ব্যবহার করে, যা বিভিন্ন ধরনের ডেটা ধারণ করতে পারে।
নন-টাইপ টেমপ্লেট প্যারামিটার
C++ তে টেমপ্লেট প্যারামিটার শুধু ডেটা টাইপই হতে পারে না, এটি কোনো নির্দিষ্ট মানও হতে পারে, যাকে নন-টাইপ টেমপ্লেট প্যারামিটার বলা হয়।
#include <iostream>
template <typename T, int size>
class Array {
private:
T arr[size];
public:
void set(int index, T value) {
if (index >= 0 && index < size) {
arr[index] = value;
}
}
T get(int index) {
if (index >= 0 && index < size) {
return arr[index];
}
return T(); // ডিফল্ট মান রিটার্ন
}
};
int main() {
Array<int, 5> arr;
arr.set(0, 10);
arr.set(1, 20);
std::cout << "Element at index 0: " << arr.get(0) << std::endl;
std::cout << "Element at index 1: " << arr.get(1) << std::endl;
return 0;
}ব্যাখ্যা:
sizeএখানে একটি নন-টাইপ প্যারামিটার যাArrayক্লাসের অ্যারের আকার নির্ধারণ করে।
টেমপ্লেট স্পেশালাইজেশন (Template Specialization)
কিছু ক্ষেত্রে নির্দিষ্ট ডেটা টাইপের জন্য আলাদা আচরণ প্রয়োজন হতে পারে। এই জন্য টেমপ্লেট স্পেশালাইজেশন ব্যবহার করা হয়।
#include <iostream>
template <typename T>
class Printer {
public:
void print(T value) {
std::cout << "Value: " << value << std::endl;
}
};
// টেমপ্লেট স্পেশালাইজেশন
template <>
class Printer<char> {
public:
void print(char value) {
std::cout << "Character: " << value << std::endl;
}
};
int main() {
Printer<int> intPrinter;
Printer<char> charPrinter;
intPrinter.print(100);
charPrinter.print('A');
return 0;
}ব্যাখ্যা:
- এখানে
Printerক্লাসটি স্পেশালাইজ করা হয়েছেcharটাইপের জন্য। সাধারণprintমেথডের পরিবর্তেcharটাইপের জন্য আলাদা মেথড ব্যবহার করা হয়েছে।
উপসংহার
C++ তে টেমপ্লেট প্রোগ্রামিংয়ের একটি শক্তিশালী বৈশিষ্ট্য যা কোডের পুনরায় ব্যবহারযোগ্যতা বৃদ্ধি করে। ফাংশন টেমপ্লেট এবং ক্লাস টেমপ্লেট ব্যবহার করে আমরা একাধিক ডেটা টাইপের জন্য সাধারণ কোড তৈরি করতে পারি। এছাড়া টেমপ্লেট স্পেশালাইজেশন এবং নন-টাইপ টেমপ্লেট প্যারামিটার ব্যবহার করে আমরা আরও নির্দিষ্ট এবং প্রয়োজনমাফিক প্রোগ্রামিং করতে পারি।
Templates C++ এর একটি গুরুত্বপূর্ণ বৈশিষ্ট্য, যা প্রোগ্রামিংয়ের সময় ডেটা টাইপ নির্দিষ্ট না করে ফাংশন বা ক্লাস তৈরি করতে দেয়। Templates ব্যবহার করে আমরা একবারে একটি ফাংশন বা ক্লাস তৈরি করে সেটিকে বিভিন্ন ডেটা টাইপের সাথে ব্যবহার করতে পারি, যা কোডের পুনঃব্যবহারযোগ্যতা বাড়ায় এবং টাইপ নিরপেক্ষ প্রোগ্রামিংকে সম্ভব করে তোলে।
C++ এ দুই ধরনের টেমপ্লেট রয়েছে:
- Function Templates
- Class Templates
Function Templates
Function Template হলো এমন একটি টেমপ্লেট, যা একাধিক ডেটা টাইপের সাথে কাজ করতে পারে। এটি ব্যবহার করে একবার ফাংশন তৈরি করলে সেটিকে বিভিন্ন ডেটা টাইপের সাথে ব্যবহার করা যায়। Function Template সাধারণত template কীওয়ার্ডের সাথে ব্যবহৃত হয় এবং ডেটা টাইপ typename বা class কীওয়ার্ডের মাধ্যমে নির্ধারণ করা হয়।
Function Template এর সাধারণ গঠন
template <typename T>
T functionName(T parameter1, T parameter2) {
// ফাংশন বডি
}এখানে T একটি টেমপ্লেট টাইপ প্যারামিটার, যা ফাংশন কল করার সময় নির্ধারণ করা হয়।
উদাহরণ: দুইটি ভ্যালুর মধ্যে বড়টি বের করার জন্য Function Template
#include <iostream>
template <typename T>
T getMax(T a, T b) {
return (a > b) ? a : b;
}
int main() {
std::cout << "Max of 10 and 20: " << getMax(10, 20) << std::endl; // int টাইপ
std::cout << "Max of 3.5 and 7.2: " << getMax(3.5, 7.2) << std::endl; // double টাইপ
std::cout << "Max of 'A' and 'Z': " << getMax('A', 'Z') << std::endl; // char টাইপ
return 0;
}আউটপুট:
Max of 10 and 20: 20
Max of 3.5 and 7.2: 7.2
Max of 'A' and 'Z': Zএখানে getMax একটি Function Template, যা int, double, এবং char টাইপের ভ্যালুর জন্য একইভাবে কাজ করেছে।
Class Templates
Class Template হলো এমন একটি টেমপ্লেট, যা বিভিন্ন ডেটা টাইপের অবজেক্ট তৈরি করতে পারে। Class Template ব্যবহার করে একবার ক্লাস তৈরি করলে সেটি বিভিন্ন ডেটা টাইপের জন্য ব্যবহার করা যায়, যা কোডের পুনঃব্যবহারযোগ্যতা বাড়ায়।
Class Template এর সাধারণ গঠন
template <typename T>
class ClassName {
public:
T data;
ClassName(T value) : data(value) {}
void display() {
std::cout << "Value: " << data << std::endl;
}
};এখানে T একটি টেমপ্লেট টাইপ প্যারামিটার, যা ক্লাসের ডেটা টাইপ নির্দেশ করে।
উদাহরণ: একাধিক ডেটা টাইপের জন্য একটি Class Template
#include <iostream>
template <typename T>
class Storage {
T data;
public:
Storage(T value) : data(value) {}
T getData() const {
return data;
}
void setData(T value) {
data = value;
}
};
int main() {
Storage<int> intStorage(100); // int টাইপ
Storage<double> doubleStorage(3.14); // double টাইপ
std::cout << "Integer Storage: " << intStorage.getData() << std::endl;
std::cout << "Double Storage: " << doubleStorage.getData() << std::endl;
intStorage.setData(200);
std::cout << "Updated Integer Storage: " << intStorage.getData() << std::endl;
return 0;
}আউটপুট:
Integer Storage: 100
Double Storage: 3.14
Updated Integer Storage: 200এখানে Storage একটি Class Template, যা int এবং double টাইপের ডেটা সংরক্ষণ এবং প্রক্রিয়াকরণ করতে ব্যবহৃত হয়েছে।
Function Template এবং Class Template এর ব্যবহারিক সুবিধা
- পুনঃব্যবহারযোগ্যতা: একবার টেমপ্লেট তৈরি করলে সেটি বিভিন্ন ডেটা টাইপের জন্য ব্যবহার করা যায়, যা কোডের পুনঃব্যবহারযোগ্যতা বাড়ায়।
- টাইপ সেফটি: টেমপ্লেট ব্যবহার করে টাইপ নির্ভর কোড তৈরি করা যায়, যা টাইপ সম্পর্কিত ত্রুটি কমাতে সাহায্য করে।
- সহজ এবং কার্যকর: একই কাজের জন্য বারবার ভিন্ন ভিন্ন ডেটা টাইপের জন্য ফাংশন বা ক্লাস লেখার প্রয়োজন হয় না, টেমপ্লেট ব্যবহার করে একবারে সব কাজ করা যায়।
একাধিক টেমপ্লেট প্যারামিটার
C++ এ একই সাথে একাধিক টেমপ্লেট প্যারামিটার ব্যবহার করা যায়, যা ক্লাস বা ফাংশনে একাধিক ধরনের ডেটা নিয়ে কাজ করতে সহায়ক।
উদাহরণ: একাধিক টেমপ্লেট প্যারামিটার সহ Class Template
#include <iostream>
template <typename T1, typename T2>
class Pair {
T1 first;
T2 second;
public:
Pair(T1 a, T2 b) : first(a), second(b) {}
void display() {
std::cout << "First: " << first << ", Second: " << second << std::endl;
}
};
int main() {
Pair<int, double> p1(10, 3.14);
Pair<std::string, int> p2("Age", 30);
p1.display();
p2.display();
return 0;
}আউটপুট:
First: 10, Second: 3.14
First: Age, Second: 30এখানে Pair ক্লাসে দুইটি টেমপ্লেট প্যারামিটার T1 এবং T2 ব্যবহার করা হয়েছে, যা বিভিন্ন ডেটা টাইপের জন্য ব্যবহার করা হয়েছে।
উপসংহার
- Function Template: একবারে একটি ফাংশন তৈরি করে সেটিকে বিভিন্ন ডেটা টাইপের সাথে ব্যবহার করা যায়।
- Class Template: একবারে একটি ক্লাস তৈরি করে সেটিকে বিভিন্ন ডেটা টাইপের অবজেক্ট তৈরি করতে ব্যবহার করা যায়।
- একাধিক টেমপ্লেট প্যারামিটার: একাধিক ডেটা টাইপের সাথে কাজ করার জন্য টেমপ্লেট প্যারামিটার ব্যবহার করা যায়।
C++ এ Templates ব্যবহার করে প্রোগ্রামাররা সাধারণ ফাংশন বা ক্লাস তৈরি করতে পারে, যা বিভিন্ন ডেটা টাইপের সাথে কাজ করতে পারে, এবং এটি কোডের পুনঃব্যবহারযোগ্যতা এবং গঠনকে আরও কার্যকর করে তোলে।
C++ এ Template Specialization এবং Partial Specialization এমন বৈশিষ্ট্য যা templates এর ক্ষেত্রে custom behavior (বিশেষ আচরণ) নির্দিষ্ট করতে ব্যবহার করা হয়। Templates একটি সাধারণ কোড ডিজাইন প্যাটার্ন, যেখানে আপনি একটি ফাংশন বা ক্লাসের জন্য সাধারণ কোড লিখে, তার পরামিতি টাইপের ভিত্তিতে সেই কোডের আচরণ পরিবর্তন করতে পারেন। তবে, কখনও কখনও আপনার প্রয়োজন হতে পারে কিছু বিশেষ পরিস্থিতিতে টেমপ্লেটের আচরণ পরিবর্তন করার, এটি করতে Template Specialization এবং Partial Specialization ব্যবহার করা হয়।
১. Template Specialization
Template Specialization হল একটি প্রক্রিয়া যেখানে আপনি একটি সাধারণ টেমপ্লেটের জন্য বিশেষ আচরণ নির্ধারণ করতে পারেন নির্দিষ্ট টাইপের জন্য। এটি তখন ব্যবহার করা হয় যখন একটি টেমপ্লেটের জন্য আপনি একটি নির্দিষ্ট ইনপুট টাইপের জন্য আলাদা আচরণ চাচ্ছেন।
Full Specialization
ফুল স্পেশালাইজেশনের মধ্যে, আপনি একটি নির্দিষ্ট টেমপ্লেট ইন্সট্যানশিয়েশন (specialization) তৈরি করেন। এর মাধ্যমে আপনি টেমপ্লেটের একটি নির্দিষ্ট ধরনের জন্য আলাদা কোড লিখতে পারেন।
উদাহরণ: Template Specialization (Full Specialization)
#include <iostream>
using namespace std;
// সাধারণ টেমপ্লেট
template <typename T>
void print(T value) {
cout << "General Template: " << value << endl;
}
// ফুল স্পেশালাইজেশন (int টাইপের জন্য)
template <>
void print<int>(int value) {
cout << "Specialized Template for int: " << value << endl;
}
int main() {
print(5); // Specialized template for int
print(3.14); // General template for double
return 0;
}আউটপুট:
Specialized Template for int: 5
General Template: 3.14এখানে, print<int> এর জন্য একটি ফুল স্পেশালাইজেশন তৈরি করা হয়েছে, যা int টাইপের জন্য আলাদা আচরণ প্রদর্শন করছে, এবং অন্যসব টাইপের জন্য সাধারণ টেমপ্লেট কাজ করছে।
২. Partial Specialization
Partial Specialization হল যখন আপনি একটি টেমপ্লেটের জন্য কিছু প্যারামিটার স্পেশালাইজ করেন, কিন্তু সব প্যারামিটার নয়। এর মাধ্যমে আপনি কিছু অংশে স্পেশালাইজেশন প্রদান করতে পারেন, কিন্তু পুরো প্যারামিটার সেটের জন্য নয়।
উদাহরণ: Template Partial Specialization
#include <iostream>
using namespace std;
// সাধারণ টেমপ্লেট
template <typename T, typename U>
void print(T value1, U value2) {
cout << "General Template: " << value1 << ", " << value2 << endl;
}
// পার্সিয়াল স্পেশালাইজেশন (যখন প্রথম টাইপ int হয়)
template <typename U>
void print<int, U>(int value1, U value2) {
cout << "Partial Specialization for int: " << value1 << ", " << value2 << endl;
}
int main() {
print(5, 3.14); // Partial specialization for int and double
print("Hello", 10); // General template for string and int
return 0;
}আউটপুট:
Partial Specialization for int: 5, 3.14
General Template: Hello, 10এখানে, print<int, U> এর জন্য partial specialization করা হয়েছে, যেখানে প্রথম প্যারামিটার int এবং দ্বিতীয় প্যারামিটার U যেকোনো ধরনের হতে পারে।
৩. Template Specialization vs Partial Specialization
- Full Specialization: এখানে আপনি টেমপ্লেটের সব প্যারামিটার স্পেশালাইজ করেন। এটি শুধুমাত্র একটি নির্দিষ্ট ইনপুট টাইপের জন্য কাজ করে। অন্য টাইপের জন্য সাধারণ টেমপ্লেট ব্যবহৃত হয়।
- Partial Specialization: এখানে কিছু প্যারামিটার স্পেশালাইজ করা হয়, কিন্তু সব প্যারামিটার নয়। এটি আরও নমনীয় এবং সাধারণ ক্ষেত্রে ব্যবহার করা যায়।
তুলনা:
| বিশেষণ | Full Specialization | Partial Specialization |
|---|---|---|
| ব্যবহার | নির্দিষ্ট টাইপের জন্য এক্সিকিউট করা | কিছু প্যারামিটার স্পেশালাইজ করা |
| উদাহরণ | template <> void print<int>(int) | template <typename U> void print<int, U>(int, U) |
| বৈশিষ্ট্য | শুধুমাত্র নির্দিষ্ট টেমপ্লেটের জন্য কাজ করে | কিছু প্যারামিটার কাস্টমাইজ করা যেতে পারে |
| নমনীয়তা | কম নমনীয়, কারণ পুরোপুরি স্পেশালাইজড | বেশি নমনীয়, কিছু প্যারামিটার ছেড়ে দেয় |
৪. Template Specialization এবং Partial Specialization এর প্রয়োগ
- Full Specialization সাধারণত ব্যবহৃত হয় যখন আপনি বিশেষ কিছু ইনপুট টাইপ বা প্যারামিটার এর জন্য সম্পূর্ণ আলাদা আচরণ চান।
- Partial Specialization ব্যবহৃত হয় যখন আপনি একটি সাধারণ আচরণ বজায় রেখে, শুধুমাত্র কিছু প্যারামিটার স্পেশালাইজ করতে চান। এটি সাধারণ টেমপ্লেট কনসেপ্টের জন্য আরও উন্নত এবং নমনীয় সমাধান প্রদান করে।
উদাহরণ: ট্রেডার ক্লাসে স্পেশালাইজেশন (Full and Partial)
#include <iostream>
#include <string>
using namespace std;
// সাধারণ টেমপ্লেট
template <typename T>
class Trader {
public:
void trade(T amount) {
cout << "Trading " << amount << endl;
}
};
// `std::string` এর জন্য ফুল স্পেশালাইজেশন
template <>
class Trader<string> {
public:
void trade(string amount) {
cout << "Trading a string amount: " << amount << endl;
}
};
// পার্সিয়াল স্পেশালাইজেশন (যখন T = int)
template <typename U>
class Trader<int, U> {
public:
void trade(int amount, U asset) {
cout << "Trading " << amount << " units of " << asset << endl;
}
};
int main() {
Trader<int> trader1; // সাধারন টেমপ্লেট
trader1.trade(100); // Trading 100
Trader<string> trader2; // ফুল স্পেশালাইজেশন (string এর জন্য)
trader2.trade("100 USD"); // Trading a string amount: 100 USD
Trader<int, string> trader3; // পার্সিয়াল স্পেশালাইজেশন (int এবং string)
trader3.trade(200, "Stocks"); // Trading 200 units of Stocks
return 0;
}আউটপুট:
Trading 100
Trading a string amount: 100 USD
Trading 200 units of Stocksএখানে, Trader<string> এর জন্য ফুল স্পেশালাইজেশন এবং Trader<int, string> এর জন্য পার্সিয়াল স্পেশালাইজেশন করা হয়েছে।
উপসংহার
- Full Specialization: একটি নির্দিষ্ট টাইপের জন্য টেমপ্লেটের সম্পূর্ণ আচরণ পরিবর্তন করে।
- Partial Specialization: কিছু প্যারামিটার স্পেশালাইজ করা হয়, যা পুরোপুরি কাস্টমাইজ করার জন্য আরও নমনীয় এবং সাধারণ টেমপ্লেট ব্যবহারের অনুমতি দেয়।
- উভয়ই generic programming এবং type safety বজায় রাখে, তবে বিশেষ পরিস্থিতিতে আরও উপযোগী হতে পারে যেখানে টেমপ্লেটের আচরণ নির্দিষ্ট ইনপুট টাইপের জন্য আলাদা করতে হয়।
Variadic Templates and Fold Expressions in C++
Variadic Templates এবং Fold Expressions হল C++11 এবং C++17-এ যোগ করা দুটি শক্তিশালী বৈশিষ্ট্য যা আপনাকে আরও সাধারণ এবং নমনীয় কোড লেখার সুযোগ দেয়। এই বৈশিষ্ট্যগুলি বিশেষভাবে কাজে লাগে যখন আপনি একাধিক আর্গুমেন্ট নিয়ে কাজ করছেন এবং ঐতিহ্যগত ফাংশন প্রোটোটাইপগুলি যথেষ্ট নমনীয় নয়।
১. Variadic Templates (ভ্যারিয়াডিক টেমপ্লেট)
Variadic Templates C++-এ একটি ফিচার যা আপনাকে একাধিক আর্গুমেন্ট গ্রহণ করার জন্য একটি টেমপ্লেট ক্লাস বা ফাংশন ডিফাইন করতে দেয়। এটি ... (ellipsis) সিনট্যাক্স ব্যবহার করে এবং ডিপ্লিকেট আর্গুমেন্ট ছাড়াই একাধিক প্যারামিটার নিয়ে কাজ করতে সাহায্য করে।
বৈশিষ্ট্য:
- একাধিক আর্গুমেন্ট গ্রহণ: Variadic Templates আপনাকে যেকোনো সংখ্যক আর্গুমেন্ট পাস করার সুযোগ দেয়।
- রিকারসিভ (Recursive) টেমপ্লেট: Variadic Templates সাধারণত রিকারসিভ টেমপ্লেট ফাংশন বা ক্লাসের মাধ্যমে কাজ করে, যেখানে প্রতিটি আর্গুমেন্ট আলাদাভাবে প্রক্রিয়া করা হয়।
উদাহরণ: Variadic Function Template
#include <iostream>
// Variadic template function definition
template <typename T>
void print(T arg) {
std::cout << arg << std::endl;
}
template <typename T, typename... Args>
void print(T arg, Args... args) {
std::cout << arg << " ";
print(args...); // Recursive call with remaining arguments
}
int main() {
print(1, 2.5, "Hello", 'A'); // 1 2.5 Hello A
return 0;
}আউটপুট:
1 2.5 Hello Aএখানে print ফাংশনটি একটি variadic template function, যা একাধিক আর্গুমেন্ট গ্রহণ করে এবং প্রত্যেকটি আর্গুমেন্টকে প্রিন্ট করে। প্রথমে ফাংশনটি একটি আর্গুমেন্ট নিয়ে কাজ করে, তারপর বাকি আর্গুমেন্টগুলির জন্য আবার নিজেকে কল করে (রিকারসিভ কল)।
২. Fold Expressions (ফোল্ড এক্সপ্রেশন)
Fold Expressions C++17-এ পরিচিত একটি বৈশিষ্ট্য যা variadic templates এর সাথে কাজ করে। এটি একটি নতুন সিনট্যাক্স প্রদান করে, যার মাধ্যমে আমরা সহজে একাধিক আর্গুমেন্টের ওপর অপারেশন করতে পারি, বিশেষত সেগুলিকে যোগ, গুণ, অথবা অন্যান্য কার্যকরী অপারেশন করতে।
Fold expressions variadic templates-এর উপর ভিত্তি করে কাজ করে এবং এটি একটি নতুন উপায় প্রদান করে, যেখানে আপনাকে সবার ওপর অপারেশন করার জন্য রিকারসিভ টেমপ্লেট কলের প্রয়োজন হয় না। এর মাধ্যমে একটি একক এক্সপ্রেশন দিয়ে সব আর্গুমেন্টের ওপরে কার্যকরী অপারেশন করা যায়।
সিনট্যাক্স:
- Unary fold:
(... op pack)— প্রতিটি আর্গুমেন্টে অপারেশন করতে। - Binary fold:
(pack op ... op)— প্রথম আর্গুমেন্টের সাথে পরবর্তী আর্গুমেন্টগুলো মিলিয়ে অপারেশন করা।
উদাহরণ: Unary Fold Expression
#include <iostream>
template <typename... Args>
auto sum(Args... args) {
return (args + ...); // Unary fold expression
}
int main() {
std::cout << sum(1, 2, 3, 4, 5) << std::endl; // Output: 15
return 0;
}আউটপুট:
15এখানে (args + ...) ব্যবহার করা হয়েছে, যা সমস্ত আর্গুমেন্টের ওপর যোগফল অপারেশন করে। এটি unary fold এক্সপ্রেশন, যেটি সমস্ত আর্গুমেন্টের ওপর একক অপারেশন প্রয়োগ করে।
উদাহরণ: Binary Fold Expression
#include <iostream>
template <typename... Args>
auto multiply(Args... args) {
return (args * ...); // Binary fold expression
}
int main() {
std::cout << multiply(1, 2, 3, 4) << std::endl; // Output: 24
return 0;
}আউটপুট:
24এখানে (args * ...) ব্যবহার করা হয়েছে, যা সমস্ত আর্গুমেন্টের ওপর গুণফল অপারেশন করে। এটি binary fold এক্সপ্রেশন, যেখানে সমস্ত আর্গুমেন্টকে একে একে গুণ করা হয়।
৩. Fold Expressions এর সুবিধা:
- কোড সরলীকরণ: Variadic templates এবং fold expressions দিয়ে কোড লেখা অনেক সহজ এবং পরিষ্কার হয়, বিশেষত যখন একাধিক আর্গুমেন্ট নিয়ে কাজ করতে হয়।
- রিকারসিভ কল থেকে মুক্তি: পূর্বে variadic templates ব্যবহার করার সময়, রিকারসিভ কলের মাধ্যমে একাধিক আর্গুমেন্টের ওপর অপারেশন করতে হতো। fold expressions এর মাধ্যমে আমরা রিকারসিভ কল ছাড়াই এটি করতে পারি।
- গতি: fold expressions সাধারণত রিকারসিভ টেমপ্লেট কলের তুলনায় দ্রুত হয়, কারণ এটি এক্সপ্রেশন হিসেবে অপারেশন সম্পাদন করে।
৪. Variadic Templates এবং Fold Expressions এর ব্যবহার:
উদাহরণ: মিশ্র অপারেশন এবং String Concatenation
#include <iostream>
#include <string>
template <typename... Args>
std::string concatenate(Args... args) {
return (args + ...); // Unary fold expression for string concatenation
}
int main() {
std::cout << concatenate("Hello, ", "world", "! ", "How are you?") << std::endl;
return 0;
}আউটপুট:
Hello, world! How are you?এখানে, সমস্ত স্ট্রিং আর্গুমেন্টগুলি একত্রিত (concatenate) করা হয়েছে। fold expression স্ট্রিংগুলোকে একসাথে যোগ করে।
উপসংহার
- Variadic Templates: C++-এ ফাংশন বা ক্লাসে একাধিক প্যারামিটার (আর্গুমেন্ট) নিয়ে কাজ করার জন্য একটি শক্তিশালী ফিচার।
- Fold Expressions: C++17-এ একটি নতুন বৈশিষ্ট্য যা variadic templates এর সাথে সহজে অপারেশন করার সুযোগ দেয়, বিশেষত arithmetic অপারেশনগুলোর ক্ষেত্রে।
এই দুটি বৈশিষ্ট্য C++ প্রোগ্রামিংকে আরও নমনীয়, শক্তিশালী এবং সংক্ষিপ্ত করে তোলে, বিশেষ করে যখন একাধিক আর্গুমেন্টের সাথে কাজ করতে হয়।
C++20 তে Concepts এবং Template Constraints চালু হয়েছে, যা টেমপ্লেট প্রোগ্রামিংয়ের সুবিধা এবং শক্তিশালী যাচাইকরণ প্রদান করে। Concepts একটি নতুন বৈশিষ্ট্য যা টেমপ্লেট আর্গুমেন্টগুলোর জন্য শর্ত বা বিধিনিষেধ (constraints) সন্নিবেশ করতে সহায়ক। এটি মূলত std::enable_if বা অন্যান্য সিস্টেমের তুলনায় অনেক বেশি ব্যাবহারযোগ্য এবং সরল উপায়ে টাইপ যাচাইকরণের সুবিধা প্রদান করে।
১. Concepts
Concepts একটি নতুন ধরনের ডেটা টাইপ প্রপার্টি যা টেমপ্লেট প্যারামিটারগুলির জন্য শর্ত বা বিধিনিষেধ প্রয়োগ করে। Concepts ব্যবহারে, টাইপ বা প্যারামিটার কেমন হবে, সেই বিষয়ে স্পষ্টভাবে একটি শর্ত নির্ধারণ করা হয়। এটি কোডে টাইপ সঠিকতা যাচাই করতে সাহায্য করে এবং আরও পড়তে সুবিধাজনক করে তোলে। concept একটি বিশেষ ধরনের ক্লাস নয়, বরং একটি টেমপ্লেট প্যারামিটার জন্য শর্ত যা টেমপ্লেট আর্গুমেন্টের বৈশিষ্ট্য নির্ধারণ করে।
Concept উদাহরণ:
#include <iostream>
#include <concepts>
// একটি কনসেপ্ট তৈরি করা
template<typename T>
concept Addable = requires(T a, T b) {
{ a + b } -> std::same_as<T>; // 'a' এবং 'b' এর যোগফল টাইপ T হতে হবে
};
// একটি ফাংশন যেখানে Concept ব্যবহৃত হচ্ছে
template <Addable T>
T add(T a, T b) {
return a + b;
}
int main() {
std::cout << add(5, 3) << std::endl; // এটি কাজ করবে, কারণ 5 এবং 3 যোগফলটি একটি int
// std::cout << add("Hello", " World"); // এটি ত্রুটি দিবে, কারণ string যোগফলটি Concept এর সাথে মেলে না
return 0;
}এখানে, Addable একটি কনসেপ্ট যা যাচাই করে যে a + b অপারেশনটি টাইপ T এর জন্য বৈধ কিনা। add ফাংশনটি Addable কনসেপ্টের মাধ্যমে নিশ্চিত করে যে, শুধুমাত্র সেই ধরণের আর্গুমেন্ট গ্রহণ করা হবে, যেগুলোর জন্য + অপারেশনটি বৈধ।
২. Template Constraints
C++20 এ Template Constraints এর মাধ্যমে, আমরা টেমপ্লেট প্যারামিটারগুলোর জন্য বিভিন্ন শর্ত আরোপ করতে পারি, যেগুলোর ভিত্তিতে টেমপ্লেটের বৈধতা নির্ধারণ করা হয়। এই শর্তগুলির মাধ্যমে কিছু নির্দিষ্ট অ্যাকশন বা যাচাইকরণ করতে পারি যা C++20-এর Concepts এ ব্যাখ্যা করা হয়েছে। এই Constraints আসলে Concepts ব্যবহার করে করা হয়।
উদাহরণ: Template Constraints
#include <iostream>
#include <concepts>
// একটি কনসেপ্ট তৈরি করা
template<typename T>
concept Integral = std::is_integral_v<T>; // শুধুমাত্র ইন্টিগার টাইপ গ্রহণ করা
// টেমপ্লেট ফাংশন যেখানে কনসেপ্ট এবং কনস্ট্রেইন্ট ব্যবহার করা হচ্ছে
template <Integral T>
T multiply(T a, T b) {
return a * b;
}
int main() {
std::cout << multiply(5, 3) << std::endl; // এটি কাজ করবে, কারণ 5 এবং 3 ইন্টিগার টাইপ
// std::cout << multiply(5.5, 3.0) << std::endl; // এটি ত্রুটি দিবে, কারণ double এর জন্য Integral কনসেপ্ট কাজ করে না
return 0;
}এখানে, Integral একটি কনসেপ্ট যা নিশ্চিত করে যে টেমপ্লেট প্যারামিটার শুধুমাত্র ইন্টিগার টাইপ হবে। multiply ফাংশনটি সেই শর্ত অনুযায়ী কেবল ইন্টিগার টাইপের প্যারামিটার গ্রহণ করবে।
৩. Concepts এবং Template Constraints এর সুবিধা
- স্পষ্টতা: Concepts ব্যবহার করে টেমপ্লেট প্যারামিটারগুলির জন্য স্পষ্ট শর্ত আরোপ করা যায়, যা টাইপ সঠিকতা আরও পরিষ্কার করে তোলে।
- বাগ কমানো: Concepts এবং Template Constraints এর মাধ্যমে, কম্পাইল টাইমে ভুলগুলো ধরা পড়ে এবং প্রোগ্রামারদের জন্য তা সঠিক করতে সহায়ক হয়। এটি রানটাইমের ত্রুটিগুলোর সম্ভাবনা কমায়।
- পঠনযোগ্যতা: Concepts ব্যবহারে কোডটি পড়তে এবং বুঝতে সহজ হয়, কারণ টেমপ্লেট প্যারামিটারগুলির শর্ত সোজা এবং স্পষ্টভাবে উল্লেখ করা হয়।
- নির্ভরযোগ্যতা: Concepts ব্যবহার করে, নির্দিষ্ট শর্ত মেনে চলা উপাদানসমূহের সাথে কেবল কাজ করা যায়, ফলে নির্ভরযোগ্য প্রোগ্রামিং নিশ্চিত হয়।
৪. Concepts এর বিভিন্ন ব্যবহার
C++20 Concepts এর মাধ্যমে আরও অনেক শক্তিশালী ফিচার ব্যবহার করা সম্ভব, যেমন:
- কনসেপ্ট কম্পোজিশন: একাধিক কনসেপ্ট একসাথে ব্যবহার করে নতুন কনসেপ্ট তৈরি করা।
template <typename T>
concept Addable = requires(T a, T b) {
{ a + b } -> std::same_as<T>;
};
template <typename T>
concept Multiplicable = requires(T a, T b) {
{ a * b } -> std::same_as<T>;
};
// দুটি কনসেপ্টের মিশ্রণ
template <typename T>
concept AddableAndMultiplicable = Addable<T> && Multiplicable<T>;
template <AddableAndMultiplicable T>
T performOperations(T a, T b) {
return a + b * a; // দুটি অপারেশন একসাথে করা
}- বৈশিষ্ট্য নির্ধারণ: Concepts ব্যবহার করে আপনার কোডের বৈশিষ্ট্য সহজে নির্ধারণ করতে পারেন, যেমন
std::integral,std::floating_pointইত্যাদি।
template <std::integral T>
T sum(T a, T b) {
return a + b;
}সারাংশ
- Concepts: C++20 এর একটি নতুন বৈশিষ্ট্য যা টেমপ্লেট প্যারামিটারগুলোর জন্য শর্ত আরোপ করে, এবং টেমপ্লেট টাইপ সঠিকতা সহজেই যাচাই করতে সহায়ক হয়।
- Template Constraints: Concepts এর সাহায্যে টেমপ্লেট প্যারামিটারগুলির জন্য শর্ত আরোপ এবং যাচাইকরণ করা হয়।
- ব্যবহার: Concepts এবং Constraints ব্যবহার করে কোডের স্পষ্টতা বৃদ্ধি, কম্পাইল টাইমে ত্রুটি সনাক্তকরণ এবং কোডের নিরাপত্তা নিশ্চিত করা যায়।
C++20 Concepts এবং Template Constraints নতুন ধারার টেমপ্লেট প্রোগ্রামিংয়ের জন্য অত্যন্ত শক্তিশালী টুল।
Read more