[]
দু'বার ওভারলোড করা সম্ভব ? অনুমতি দেওয়ার জন্য, এর মতো কিছু: function[3][3]
(একটি দ্বিমাত্রিক অ্যারের মতো)।
যদি এটি সম্ভব হয় তবে আমি কয়েকটি উদাহরণ কোড দেখতে চাই।
[]
দু'বার ওভারলোড করা সম্ভব ? অনুমতি দেওয়ার জন্য, এর মতো কিছু: function[3][3]
(একটি দ্বিমাত্রিক অ্যারের মতো)।
যদি এটি সম্ভব হয় তবে আমি কয়েকটি উদাহরণ কোড দেখতে চাই।
std::vector
একটি ব্যাপ্তি নির্মাণকারীর সাথে ব্যবহার করুন : stackoverflow.com/a/25405865/610351
using array2d = std::array<std::array<int, 3>, 3>;
উত্তর:
আপনি operator[]
কোনও বস্তুটি ফেরত দিতে ওভারলোড করতে পারেন যার operator[]
ফলস্বরূপ আপনি আবার ব্যবহার করতে পারেন ।
class ArrayOfArrays {
public:
ArrayOfArrays() {
_arrayofarrays = new int*[10];
for(int i = 0; i < 10; ++i)
_arrayofarrays[i] = new int[10];
}
class Proxy {
public:
Proxy(int* _array) : _array(_array) { }
int operator[](int index) {
return _array[index];
}
private:
int* _array;
};
Proxy operator[](int index) {
return Proxy(_arrayofarrays[index]);
}
private:
int** _arrayofarrays;
};
তারপরে আপনি এটি ব্যবহার করতে পারেন:
ArrayOfArrays aoa;
aoa[3][5];
এটি কেবল একটি সাধারণ উদাহরণ, আপনি সীমান্তের চেক এবং স্টাফগুলির একটি গুচ্ছ যুক্ত করতে চান তবে আপনি ধারণাটি পাবেন।
Proxy::operator[]
ফিরে int&
আসা উচিত নয়int
std::vector<std::vector<int>>
অনুলিপি এবং অনুলিপিতে অদ্ভুত আচরণ এড়ানোর জন্য ব্যবহার করা ভাল ।
multi_array
এবং extent_gen
এই কৌশলটির ভাল উদাহরণ। boost.org/doc/libs/1_57_0/libs/mult_array/doc/…
const ArrayOfArrays arr; arr[3][5] = 42;
সংকলন এবং পরিবর্তন পাস করতে সক্ষম হবে arr[3][5]
, যা কি ব্যবহারকারীদের প্রত্যাশা থেকে একরকম ভিন্ন arr
হয় const
।
Proxy::operator[]
এই কোডটিতে কোনও রেফারেন্স দেয় না (ধরে নিলেন আপনার মন্তব্য রায়ান হেইনিংয়ের উত্তরে নয়)। আরও গুরুত্বপূর্ণ, যদি arr
কনস্ট থাকে তবে operator[]
ব্যবহার করা যাবে না। আপনাকে একটি কনস্টের সংস্করণ সংজ্ঞায়িত করতে হবে এবং অবশ্যই আপনি এটি ফিরিয়ে আনবেন const Proxy
। তারপরে Proxy
নিজেই কনস্ট এবং নন-কনস্ট্যান্ড পদ্ধতি থাকত। এবং তারপরেও আপনার উদাহরণটি এখনও সংকলন করবে না এবং প্রোগ্রামার খুশি হবে যে মহাবিশ্বে সমস্ত কিছু ভাল এবং ভাল। =)
একটি এক্সপ্রেশন x[y][z]
প্রয়োজন সমর্থন করে যে x[y]
একটি অবজেক্টের মূল্যায়ন ।d
d[z]
এর অর্থ এই যে x[y]
একটি সঙ্গে একটি বস্তু হওয়া উচিত operator[]
একটি "প্রক্সি বস্তুর" যে যে মূল্যায়ণ এছাড়াও একটি সমর্থন operator[]
।
এগুলি তাদের শৃঙ্খলার একমাত্র উপায়।
বিকল্পভাবে, operator()
একাধিক যুক্তি নিতে ওভারলোড , যেমন আপনি প্রার্থনা করতে পারেন myObject(x,y)
।
দ্বি মাত্রিক অ্যারের জন্য, বিশেষত, আপনি একক অপারেটর [] ওভারলোড নিয়ে চলে যেতে পারেন যা প্রতিটি সারির প্রথম উপাদানটিতে একটি পয়েন্টার দেয়।
তারপরে আপনি সারিটির মধ্যে প্রতিটি উপাদান অ্যাক্সেস করতে অন্তর্নির্মিত ইনডেক্সিং অপারেটরটি ব্যবহার করতে পারেন।
একটি পদ্ধতির ব্যবহার করা হচ্ছে std::pair<int,int>
:
class Array2D
{
int** m_p2dArray;
public:
int operator[](const std::pair<int,int>& Index)
{
return m_p2dArray[Index.first][Index.second];
}
};
int main()
{
Array2D theArray;
pair<int, int> theIndex(2,3);
int nValue;
nValue = theArray[theIndex];
}
অবশ্যই, আপনি maytypedef
pair<int,int>
nValue = theArray[{2,3}];
আপনি একটি প্রক্সি অবজেক্ট ব্যবহার করতে পারেন, এরকম কিছু:
#include <iostream>
struct Object
{
struct Proxy
{
Object *mObj;
int mI;
Proxy(Object *obj, int i)
: mObj(obj), mI(i)
{
}
int operator[](int j)
{
return mI * j;
}
};
Proxy operator[](int i)
{
return Proxy(this, i);
}
};
int main()
{
Object o;
std::cout << o[2][3] << std::endl;
}
আপনি যদি আমাকে কী function
, function[x]
এবং কী তা জানাতে পারেন তবে তা দুর্দান্ত হবে function[x][y]
। তবে যাইহোক আমাকে এটিকে অন্য কোথাও ঘোষিত একটি বিষয় হিসাবে বিবেচনা করা উচিত let
SomeClass function;
(যেহেতু আপনি বলেছিলেন এটি অপারেটর ওভারলোড তাই আমার মনে হয় আপনি অ্যারের মতো আগ্রহী হবেন না SomeClass function[16][32];
)
সুতরাং function
ধরনের একটি দৃষ্টান্ত হল SomeClass
। তারপরে SomeClass
, operator[]
ওভারলোডের রিটার্নের ধরণের জন্য ঘোষণার সন্ধান করুন
ReturnType operator[](ParamType);
তারপরে function[x]
টাইপটি থাকবে ReturnType
। আবার দেখুন ReturnType
জন্য operator[]
জমিদার। যদি এমন কোনও পদ্ধতি থাকে তবে আপনি তখন প্রকাশটি ব্যবহার করতে পারেন function[x][y]
।
দ্রষ্টব্য, বিপরীতে function(x, y)
, function[x][y]
2 টি পৃথক কল। সুতরাং প্রসঙ্গটিতে কোনও লক ব্যবহার না করা পর্যন্ত সংকলক বা রানটাইম পারমাণবিকতার গ্যারান্টি দেয় এটি শক্ত। অনুরূপ উদাহরণ হ'ল, লিবিসি বলে printf
পারমাণবিক, যখন operator<<
আউটপুট স্ট্রিমের ক্রমবর্ধমান ওভারলোডকে কল করা হয় না। মত একটি বিবৃতি
std::cout << "hello" << std::endl;
মাল্টি-থ্রেড অ্যাপ্লিকেশনটিতে সমস্যা থাকতে পারে তবে এর মতো কিছু
printf("%s%s", "hello", "\n");
ভাল.
#include<iostream>
using namespace std;
class Array
{
private: int *p;
public:
int length;
Array(int size = 0): length(size)
{
p=new int(length);
}
int& operator [](const int k)
{
return p[k];
}
};
class Matrix
{
private: Array *p;
public:
int r,c;
Matrix(int i=0, int j=0):r(i), c(j)
{
p= new Array[r];
}
Array& operator [](const int& i)
{
return p[i];
}
};
/*Driver program*/
int main()
{
Matrix M1(3,3); /*for checking purpose*/
M1[2][2]=5;
}
struct test
{
using array_reference = int(&)[32][32];
array_reference operator [] (std::size_t index)
{
return m_data[index];
}
private:
int m_data[32][32][32];
};
এটির জন্য আমার নিজের সহজ সমাধানটি খুঁজে পেয়েছি।
template<class F>
struct indexer_t{
F f;
template<class I>
std::result_of_t<F const&(I)> operator[](I&&i)const{
return f(std::forward<I>(i))1;
}
};
template<class F>
indexer_t<std::decay_t<F>> as_indexer(F&& f){return {std::forward<F>(f)};}
এটি আপনাকে ল্যাম্বদা নিতে এবং একটি সূচক তৈরি করতে দেয় ( []
সমর্থন সহ)।
ধরুন আপনার কাছে এমন একটি রয়েছে operator()
যা উভয় স্থানাঙ্ককে অনক্সে দুটি আর্গুমেন্ট হিসাবে পাস করতে সহায়তা করে। [][]
সমর্থন সমর্থন এখন :
auto operator[](size_t i){
return as_indexer(
[i,this](size_t j)->decltype(auto)
{return (*this)(i,j);}
);
}
auto operator[](size_t i)const{
return as_indexer(
[i,this](size_t j)->decltype(auto)
{return (*this)(i,j);}
);
}
এবং সম্পন্ন। কোন কাস্টম ক্লাস প্রয়োজন।
যদি কোনও [x] [y] না বলে আপনি একটি [{x, y}] বলতে চান তবে আপনি এটি করতে পারেন:
struct Coordinate { int x, y; }
class Matrix {
int** data;
operator[](Coordinate c) {
return data[c.y][c.x];
}
}
একটি বিশেষায়িত টেম্পলেট হ্যান্ডলার ব্যবহার করে একাধিক [] ওভারলোড করা সম্ভব। এটি কীভাবে কাজ করে তা কেবল দেখানোর জন্য:
#include <iostream>
#include <algorithm>
#include <numeric>
#include <tuple>
#include <array>
using namespace std;
// the number '3' is the number of [] to overload (fixed at compile time)
struct TestClass : public SubscriptHandler<TestClass,int,int,3> {
// the arguments will be packed in reverse order into a std::array of size 3
// and the last [] will forward them to callSubscript()
int callSubscript(array<int,3>& v) {
return accumulate(v.begin(),v.end(),0);
}
};
int main() {
TestClass a;
cout<<a[3][2][9]; // prints 14 (3+2+9)
return 0;
}
এবং এখন SubscriptHandler<ClassType,ArgType,RetType,N>
আগের কোডটি কাজ করার সংজ্ঞা । এটি কেবল এটি কীভাবে করা যায় তা দেখায়। এই সমাধানটি অনুকূল বা ত্রুটিমুক্ত নয় (উদাহরণস্বরূপ থ্রেডসেফ নয়)।
#include <iostream>
#include <algorithm>
#include <numeric>
#include <tuple>
#include <array>
using namespace std;
template <typename ClassType,typename ArgType,typename RetType, int N> class SubscriptHandler;
template<typename ClassType,typename ArgType,typename RetType, int N,int Recursion> class SubscriptHandler_ {
ClassType*obj;
array<ArgType,N+1> *arr;
typedef SubscriptHandler_<ClassType,ArgType,RetType,N,Recursion-1> Subtype;
friend class SubscriptHandler_<ClassType,ArgType,RetType,N,Recursion+1>;
friend class SubscriptHandler<ClassType,ArgType,RetType,N+1>;
public:
Subtype operator[](const ArgType& arg){
Subtype s;
s.obj = obj;
s.arr = arr;
arr->at(Recursion)=arg;
return s;
}
};
template<typename ClassType,typename ArgType,typename RetType,int N> class SubscriptHandler_<ClassType,ArgType,RetType,N,0> {
ClassType*obj;
array<ArgType,N+1> *arr;
friend class SubscriptHandler_<ClassType,ArgType,RetType,N,1>;
friend class SubscriptHandler<ClassType,ArgType,RetType,N+1>;
public:
RetType operator[](const ArgType& arg){
arr->at(0) = arg;
return obj->callSubscript(*arr);
}
};
template<typename ClassType,typename ArgType,typename RetType, int N> class SubscriptHandler{
array<ArgType,N> arr;
ClassType*ptr;
typedef SubscriptHandler_<ClassType,ArgType,RetType,N-1,N-2> Subtype;
protected:
SubscriptHandler() {
ptr=(ClassType*)this;
}
public:
Subtype operator[](const ArgType& arg){
Subtype s;
s.arr=&arr;
s.obj=ptr;
s.arr->at(N-1)=arg;
return s;
}
};
template<typename ClassType,typename ArgType,typename RetType> struct SubscriptHandler<ClassType,ArgType,RetType,1>{
RetType operator[](const ArgType&arg) {
array<ArgType,1> arr;
arr.at(0)=arg;
return ((ClassType*)this)->callSubscript(arr);
}
};
একটি দিয়ে std::vector<std::vector<type*>>
, আপনি কাস্টম ইনপুট অপারেটর ব্যবহার করে অভ্যন্তরীণ ভেক্টরটি তৈরি করতে পারেন যা আপনার ডেটার উপরে পুনরাবৃত্তি করে এবং প্রতিটি ডাটাতে একটি পয়েন্টার ফিরিয়ে দেয়।
উদাহরণ স্বরূপ:
size_t w, h;
int* myData = retrieveData(&w, &h);
std::vector<std::vector<int*> > data;
data.reserve(w);
template<typename T>
struct myIterator : public std::iterator<std::input_iterator_tag, T*>
{
myIterator(T* data) :
_data(data)
{}
T* _data;
bool operator==(const myIterator& rhs){return rhs.data == data;}
bool operator!=(const myIterator& rhs){return rhs.data != data;}
T* operator*(){return data;}
T* operator->(){return data;}
myIterator& operator++(){data = &data[1]; return *this; }
};
for (size_t i = 0; i < w; ++i)
{
data.push_back(std::vector<int*>(myIterator<int>(&myData[i * h]),
myIterator<int>(&myData[(i + 1) * h])));
}
এই সমাধানটিতে আপনাকে আসল এসটিএল ধারক সরবরাহ করার সুবিধা রয়েছে, সুতরাং আপনি লুপ, এসটিএল অ্যালগরিদম ইত্যাদির জন্য বিশেষ ব্যবহার করতে পারেন।
for (size_t i = 0; i < w; ++i)
for (size_t j = 0; j < h; ++j)
std::cout << *data[i][j] << std::endl;
যাইহোক, এটি পয়েন্টারগুলির ভেক্টর তৈরি করে, সুতরাং আপনি যদি এটির মতো ছোট ছোট ডেটাস্ট্রাকচার ব্যবহার করেন তবে আপনি সরাসরি অ্যারের ভিতরে থাকা সামগ্রীটি অনুলিপি করতে পারেন।
কোডের উদাহরণ:
template<class T>
class Array2D
{
public:
Array2D(int a, int b)
{
num1 = (T**)new int [a*sizeof(int*)];
for(int i = 0; i < a; i++)
num1[i] = new int [b*sizeof(int)];
for (int i = 0; i < a; i++) {
for (int j = 0; j < b; j++) {
num1[i][j] = i*j;
}
}
}
class Array1D
{
public:
Array1D(int* a):temp(a) {}
T& operator[](int a)
{
return temp[a];
}
T* temp;
};
T** num1;
Array1D operator[] (int a)
{
return Array1D(num1[a]);
}
};
int _tmain(int argc, _TCHAR* argv[])
{
Array2D<int> arr(20, 30);
std::cout << arr[2][3];
getchar();
return 0;
}
ভেক্টর <ভেক্টর <টি>> বা টি ** কেবল তখনই প্রয়োজন যখন আপনার ভেরিয়েবলের দৈর্ঘ্যের সারি থাকে এবং মেমরির ব্যবহার / বরাদ্দের ক্ষেত্রে যদি আপনার আয়তক্ষেত্রাকার অ্যারে প্রয়োজন হয় তার পরিবর্তে কিছু গণিত করার কথা বিবেচনা করুন! () পদ্ধতিতে দেখুন:
template<typename T > class array2d {
protected:
std::vector< T > _dataStore;
size_t _sx;
public:
array2d(size_t sx, size_t sy = 1): _sx(sx), _dataStore(sx*sy) {}
T& at( size_t x, size_t y ) { return _dataStore[ x+y*sx]; }
const T& at( size_t x, size_t y ) const { return _dataStore[ x+y*sx]; }
const T& get( size_t x, size_t y ) const { return at(x,y); }
void set( size_t x, size_t y, const T& newValue ) { at(x,y) = newValue; }
};
সি ++ 11 এবং স্ট্যান্ডার্ড লাইব্রেরি ব্যবহার করে আপনি কোডের একক লাইনে খুব সুন্দর দ্বিমাত্রিক অ্যারে তৈরি করতে পারেন:
std::array<std::array<int, columnCount>, rowCount> myMatrix {0};
std::array<std::array<std::string, columnCount>, rowCount> myStringMatrix;
std::array<std::array<Widget, columnCount>, rowCount> myWidgetMatrix;
অভ্যন্তরীণ ম্যাট্রিক্সগুলি সারিগুলির প্রতিনিধিত্ব করে সিদ্ধান্ত নিয়ে আপনি একটি myMatrix[y][x]
সিনট্যাক্স সহ ম্যাট্রিক্স অ্যাক্সেস করতে পারেন :
myMatrix[0][0] = 1;
myMatrix[0][3] = 2;
myMatrix[3][4] = 3;
std::cout << myMatrix[3][4]; // outputs 3
myStringMatrix[2][4] = "foo";
myWidgetMatrix[1][5].doTheStuff();
এবং আপনি for
আউটপুট জন্য রেঞ্জযুক্ত ব্যবহার করতে পারেন :
for (const auto &row : myMatrix) {
for (const auto &elem : row) {
std::cout << elem << " ";
}
std::cout << std::endl;
}
(অভ্যন্তরীণ array
প্রতিনিধিত্বকারী কলামগুলি সিদ্ধান্ত নেওয়া একটি foo[x][y]
সিনট্যাক্সের অনুমতি দেয় তবে for(;;)
আউটপুট প্রদর্শনের জন্য আপনাকে ক্লামিয়ার লুপ ব্যবহার করতে হবে ))
আমার 5 সেন্ট।
আমি স্বজ্ঞাতভাবে জানতাম আমার প্রচুর বয়লারপ্লেট কোড করা দরকার।
এজন্য অপারেটরের পরিবর্তে [], আমি ওভারলোডেড অপারেটর (ইনট, ইনট) করেছি। তারপরে চূড়ান্ত ফলাফলটিতে এম [1] [2] এর পরিবর্তে আমি এম করেছি (1,2)
আমি জানি এটি বিবিধ বিষয়, তবে এটি এখনও খুব স্বজ্ঞাত এবং গাণিতিক লিপির মতো দেখতে।
সবচেয়ে সংক্ষিপ্ত এবং সহজ সমাধান:
class Matrix
{
public:
float m_matrix[4][4];
// for statements like matrix[0][0] = 1;
float* operator [] (int index)
{
return m_matrix[index];
}
// for statements like matrix[0][0] = otherMatrix[0][0];
const float* operator [] (int index) const
{
return m_matrix[index];
}
};
operator()(int, int)
পরিবর্তে ...