আপনি কীভাবে সি ++ তে কোনও বস্তুকে সিরিয়ালাইজ করবেন?


87

আমার কাছে অবজেক্টগুলির একটি ছোট শ্রেণিবিন্যাস রয়েছে যা সকেট সংযোগের মাধ্যমে সিরিয়ালাইজ করতে এবং প্রেরণ করতে হবে। আমার উভয়টি অবজেক্টটিকে সিরিয়ালাইজ করতে হবে, তারপরে এটি কী ধরণের তার ভিত্তিতে এটি ডিসরিয়ালাইজ করা উচিত। সি ++ এ (জাভাতে যেমন রয়েছে) তেমন কোনও সহজ উপায় আছে?

কোন সি ++ সিরিয়ালাইজেশন অনলাইন কোড নমুনা বা টিউটোরিয়াল আছে?

সম্পাদনা: পরিষ্কার করে বলার জন্য, আমি কোনও বস্তুকে বাইটের অ্যারে রূপান্তর করার জন্য পদ্ধতিগুলি সন্ধান করছি, তারপরে আবার কোনও বস্তুতে ফিরে আসব। আমি সকেট সংক্রমণ পরিচালনা করতে পারি।


4
পরীক্ষা করে দেখুন গুগল :: protobuf , এটা খুবই শক্তিশালী এবং দ্রুত বাইনারি ধারাবাহিকতাতে জন্য লাইব্রেরী। আমরা এটিকে বুস্ট :: এশিয়া ইত্যাদি সহ সফলভাবে ব্যবহার করেছি
কেতন

4
দৃ ST়তা প্রয়োগের সাথে মুক্ত করুন [STLPLUS] [1] দেখুন। [1]: stlplus.sourceforge.net
lsalamon

4
প্রদত্ত উত্তরগুলি আসলে কীভাবে সিরিয়াল করতে হয় তা ব্যাখ্যা করে না । এর মধ্যে একটি বুস্ট সিরিয়ালাইজেশন লাইব্রেরি সরবরাহ করে, অন্যটি একটি নিষ্পাপ বাস্তবায়নে গোটচগুলি ব্যাখ্যা করে। যেহেতু এটি সি ++ - প্রায়শই জিজ্ঞাসিত প্রশ্ন, আসলে কেউ কি এর উত্তর দিতে পারে?
অজ্ঞাত

উত্তর:


56

সিরিয়ালাইজেশন সম্পর্কে কথা বলছি, বুস্ট সিরিয়ালাইজেশন এপিআই আমার মনে আসে। নেট থেকে সিরিয়ালযুক্ত তথ্য প্রেরণ করার জন্য, আমি হয় বার্কলে সকেট বা এশিও লাইব্রেরি ব্যবহার করব

সম্পাদনা করুন:
আপনি যদি বাইট অ্যারেতে আপনার জিনিসগুলি সিরিয়ালাইজ করতে চান তবে আপনি নিম্নলিখিত উপায়ে বুস্ট সিরিয়ালাইজারটি ব্যবহার করতে পারেন (টিউটোরিয়াল সাইট থেকে নেওয়া):

#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
class gps_position
{
private:
    friend class boost::serialization::access;
    template<class Archive>
    void serialize(Archive & ar, const unsigned int version)
    {
        ar & degrees;
        ar & minutes;
        ar & seconds;
    }
    int degrees;
    int minutes;
    float seconds;

public:
    gps_position(){};
    gps_position(int d, int m, float s) :
    degrees(d), minutes(m), seconds(s)
    {}
};

আসল সিরিয়ালাইজেশন তখন বেশ সহজ:

#include <fstream>
std::ofstream ofs("filename.dat", std::ios::binary);

    // create class instance
    const gps_position g(35, 59, 24.567f);

    // save data to archive
    {
        boost::archive::binary_oarchive oa(ofs);
        // write class instance to archive
        oa << g;
        // archive and stream closed when destructors are called
    }

ডেসারিয়ালাইজেশন একটি উপমা পদ্ধতিতে কাজ করে।

এছাড়াও এমন পদ্ধতি রয়েছে যা আপনাকে পয়েন্টারগুলির সিরিয়ালাইজেশন পরিচালনা করতে দেয় (জটিল ডাটা স্ট্রাকচারের মতো ট্রেস ইত্যাদি কোনও সমস্যা নয়), উত্পন্ন ক্লাস এবং আপনি বাইনারি এবং পাঠ্য সিরিয়ালের মধ্যে চয়ন করতে পারেন। সমস্ত এসটিএল কন্টেইনারগুলি বাক্সের বাইরে সমর্থিত।


এটি একটি সি ++ প্রশ্ন, কীভাবে আসে জিপিএস_পজিশন ক্লাসটি ওভারলোডিং << অপারেটর। কোনও বন্ধু ফাংশন সংজ্ঞায়িত করা হয়নি
ভিসেন্টে বোলেয়া

"বন্ধুত্ব বর্ধন :: সিরিয়ালাইজেশন :: অ্যাক্সেস" লক্ষ্য করুন। এটি শ্রেণিবদ্ধ সদস্যদের ব্যক্তিগত থাকলেও সিরিয়ালাইজেশন লাইব্রেরি ফাংশনের অ্যাক্সেস সরবরাহ করে।
রবার্ট রেমি

13

কিছু ক্ষেত্রে, সাধারণ ধরণের সাথে কাজ করার সময়, আপনি এটি করতে পারেন:

object o;
socket.write(&o, sizeof(o));

প্রমাণের ধারণা বা প্রথম খসড়া হিসাবে এটি ঠিক আছে, তাই আপনার দলের অন্যান্য সদস্যরা অন্য অংশে কাজ চালিয়ে যেতে পারেন working

তবে যত তাড়াতাড়ি বা পরে, সাধারণত তাড়াতাড়ি , এটি আপনাকে আঘাত করবে!

আপনি এতে ইস্যুগুলি চালিয়ে যান:

  • ভার্চুয়াল পয়েন্টার টেবিলগুলি দূষিত হবে।
  • পয়েন্টারগুলি (ডেটা / সদস্য / ফাংশনে) দূষিত হবে।
  • বিভিন্ন মেশিনে প্যাডিং / প্রান্তিককরণের পার্থক্য।
  • বড় / লিটল-এন্ডিয়ান বাইট ক্রম সংক্রান্ত সমস্যা।
  • ভাসা / ডাবল বাস্তবায়নে বিভিন্নতা।

(এছাড়াও আপনি প্রাপ্তি দিক থেকে কী আনপ্যাক করছেন তা আপনার জানতে হবে))

আপনি প্রতিটি শ্রেণীর জন্য নিজের মার্শালিং / আনমারশেলিং পদ্ধতিগুলি বিকাশ করে এটিতে উন্নতি করতে পারেন। (আদর্শভাবে ভার্চুয়াল, সুতরাং এগুলি সাবক্লাসগুলিতে প্রসারিত করা যায়)) কয়েকটি সাধারণ ম্যাক্রো আপনাকে বড় / ছোট-এন্ডিয়ান-নিরপেক্ষ ক্রমে বিভিন্ন দ্রুত বেসিক প্রকারগুলি দ্রুত লিখতে দেয়।

তবে সেই ধরণের কাজটি আরও উন্নত এবং আরও সহজেই বুস্টের সিরিয়ালাইজেশন লাইব্রেরির মাধ্যমে পরিচালিত হয় ।


এটাই আমি ভাবছিলাম। তবে আমি যেমন একটি নেটওয়ার্ক স্ট্রিমিতে সিরিয়ালাইজ করতে চাই, এটি মোটেও কাজ করে না। অন্তত শেষ এবং বিভিন্ন প্ল্যাটফর্মের কারণে। তবে আমি জানতাম না যে এটি ভার্চুয়াল পয়েন্টারগুলিকে দূষিত করে। ধন্যবাদ =)
আত্মহত্যা

5

বস্তুগুলিকে সিরিয়ালাইজ করতে আপনি ব্যবহার করতে পারেন এমন সাধারণ প্যাটার্ন রয়েছে। মৌলিক আদিম হ'ল এই দুটি ফাংশন যা আপনি পুনরাবৃত্তিকারীদের কাছ থেকে পড়তে এবং লিখতে পারেন:

template <class OutputCharIterator>
void putByte(char byte, OutputCharIterator &&it)
{
    *it = byte;
    ++it;
}


template <class InputCharIterator>
char getByte(InputCharIterator &&it, InputCharIterator &&end)
{
    if (it == end)
    {
        throw std::runtime_error{"Unexpected end of stream."};
    }

    char byte = *it;
    ++it;
    return byte;
}

তারপরে সিরিয়ালাইজেশন এবং ডিসরিয়ালাইজেশন ফাংশনগুলি নিদর্শন অনুসরণ করে:

template <class OutputCharIterator>
void serialize(const YourType &obj, OutputCharIterator &&it)
{
    // Call putbyte or other serialize overloads.
}

template <class InputCharIterator>
void deserialize(YourType &obj, InputCharIterator &&it, InputCharIterator &&end)
{
    // Call getByte or other deserialize overloads.
}

ক্লাসগুলির জন্য আপনি ADL ব্যবহার করে ওভারলোডটি সন্ধানের জন্য বন্ধু ফাংশন প্যাটার্নটি ব্যবহার করতে পারেন:

class Foo
{
    int internal1, internal2;
    
    // So it can be found using ADL and it accesses private parts.
    template <class OutputCharIterator>
    friend void serialize(const Foo &obj, OutputCharIterator &&it)
    {
        // Call putByte or other serialize overloads.
    }

    // Deserialize similar.
};

তারপরে আপনার প্রোগ্রামে আপনি সিরিয়ালীকরণ করতে এবং এই জাতীয় কোনও ফাইলটিতে আপত্তি করতে পারেন:

std::ofstream file("savestate.bin");
serialize(yourObject, std::ostreambuf_iterator<char>(file));

তারপরে পড়ুন:

std::ifstream file("savestate.bin");
deserialize(yourObject, std::istreamBuf_iterator<char>(file), std::istreamBuf_iterator<char>());

আমার পুরানো উত্তর এখানে:

সিরিয়ালাইজেশন মানে আপনার বস্তুকে বাইনারি ডেটাতে পরিণত করা। যদিও ডিসরিয়ালাইজেশন অর্থ ডেটা থেকে কোনও বস্তু পুনরুদ্ধার।

সিরিয়ালাইজ করার সময় আপনি কোনও uint8_tভেক্টরে বাইটস চাপছেন। আনসিরিয়ালাইজ করার সময় আপনি কোনও uint8_tভেক্টর থেকে বাইট পড়ছেন ।

স্টাফিয়াল সিরিয়ালকরণের সময় আপনি নিখুঁত নিদর্শনগুলি নিয়োগ করতে পারেন।

প্রতিটি সিরিয়ালাইজযোগ্য শ্রেণীর একটি serialize(std::vector<uint8_t> &binaryData)বা অনুরূপ স্বাক্ষরযুক্ত ফাংশন থাকা উচিত যা সরবরাহিত ভেক্টরটিতে এর বাইনারি উপস্থাপনা লিখবে। তারপরে এই ফাংশনটি এই ভেক্টরটিকে তার সদস্যের ক্রমিক ক্রিয়াকলাপে নামিয়ে দিতে পারে যাতে তারা এতে তাদের স্টাফও লিখতে পারে।

যেহেতু ডেটা উপস্থাপনা বিভিন্ন আর্কিটেকচারে আলাদা হতে পারে। কীভাবে ডেটা উপস্থাপন করবেন তা আপনার একটি স্কিম খুঁজে বের করতে হবে।

বেসিকগুলি থেকে শুরু করা যাক:

পূর্ণসংখ্যার ডেটা ক্রমিক করা হচ্ছে

সামান্য এন্ডিয়ান ক্রমে বাইটগুলি লিখুন। অথবা আকারের বিষয়ে বিবেচনায় থাকলে ভেরেন্টের উপস্থাপনা ব্যবহার করুন।

সামান্য এন্ডিয়ান ক্রমে সিরিয়ালাইজেশন:

data.push_back(integer32 & 0xFF);
data.push_back((integer32 >> 8) & 0xFF);
data.push_back((integer32 >> 16) & 0xFF);
data.push_back((integer32 >> 24) & 0xFF);

সামান্য এডিয়ান অর্ডার থেকে ডিসরিয়ালেশন:

integer32 = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);

ভাসমান পয়েন্ট ডেটা সিরিয়ালাইজ করা হচ্ছে

যতদূর আমি জানি আইইইই 754 এর একচেটিয়া রয়েছে। আমি মূলধারার এমন কোনও স্থাপত্য সম্পর্কে জানি না যা ভাসমানদের জন্য অন্য কিছু ব্যবহার করবে। বাইট ক্রম হ'ল একমাত্র জিনিস যা আলাদা হতে পারে। কিছু স্থাপত্যগুলি সামান্য এডিয়ান ব্যবহার করে, অন্যরা বড় অ্যান্ডিয়ান বাইট ক্রম ব্যবহার করে। এর অর্থ আপনি গ্রহণের শেষে বাইটগুলি কীভাবে উচ্চতর করবেন সে সম্পর্কে আপনাকে সতর্ক হওয়া দরকার। আর একটি পার্থক্য হ'ল ডেনরমাল এবং অনন্ত এবং এনএএন মানগুলি পরিচালনা করা। তবে যতক্ষণ আপনি এই মানগুলি এড়িয়ে যান ততক্ষণ আপনার উচিত ঠিক।

ক্রমিকায়ন:

uint8_t mem[8];
memcpy(mem, doubleValue, 8);
data.push_back(mem[0]);
data.push_back(mem[1]);
...

ডিসরিয়ালাইজেশন এটি পিছনে করছে। আপনার আর্কিটেকচারের বাইট অর্ডারটি মাইন্ড করুন!

সিরিয়ালিং স্ট্রিং

প্রথমে আপনাকে একটি এনকোডিংয়ে সম্মত হওয়া দরকার। ইউটিএফ -8 সাধারণ। তারপরে এটিকে দৈর্ঘ্যের উপসর্গযুক্ত পদ্ধতি হিসাবে সঞ্চয় করুন: প্রথমে আপনি উপরে উল্লিখিত একটি পদ্ধতি ব্যবহার করে স্ট্রিংয়ের দৈর্ঘ্য সংরক্ষণ করুন, তারপরে বাই-বাই-বাই স্ট্রিংটি লিখুন।

সিরিজিকরণ অ্যারে।

তারা একটি স্ট্রিং হিসাবে একই। আপনি প্রথমে অ্যারের আকারের প্রতিনিধিত্ব করে একটি পূর্ণসংখ্যাকে সিরিয়ালাইজ করুন তারপরে এটিতে প্রতিটি বস্তুকে সিরিয়ালাইজ করুন।

পুরো বস্তু সিরিয়ালিং করা হচ্ছে

আমি আগেই বলেছি serializeযে তাদের একটি পদ্ধতি থাকা উচিত যা কোনও ভেক্টরে সামগ্রী যুক্ত করে। কোনও অবজেক্টকে আনসিরিয়ালাইজ করতে, এটির এমন একজন কনস্ট্রাক্টর থাকা উচিত যা বাইট স্ট্রিম গ্রহণ করে। এটি একটি হতে পারে istreamতবে সহজতম ক্ষেত্রে এটি কেবল একটি রেফারেন্স হতে পারেuint8_t পয়েন্টার । কনস্ট্রাক্টর স্ট্রিম থেকে এটি যে বাইটগুলি চায় তা পড়ে এবং অবজেক্টে ক্ষেত্রগুলি সেট আপ করে। যদি সিস্টেমটি ভালভাবে ডিজাইন করা হয়েছে এবং ক্ষেত্রগুলিকে অবজেক্ট ফিল্ড অর্ডারে সিরিয়ালাইজ করা হয়েছে তবে আপনি কেবলমাত্র একটি প্রারম্ভিক তালিকায় ফিল্ডটির নির্মাতাদের কাছে স্ট্রিমটি প্রেরণ করতে পারেন এবং সেগুলি সঠিক ক্রমে বিশৃঙ্খলাবদ্ধ করতে পারেন।

সিরিয়ালিং অবজেক্ট গ্রাফ

প্রথমে আপনাকে নিশ্চিত করতে হবে যে এই জিনিসগুলি সত্যই কিছু যা আপনি সিরিয়ালায়িত করতে চান to গন্তব্যে এই বিষয়গুলির উদাহরণ উপস্থিত থাকলে আপনাকে সেগুলি ক্রমিক করার দরকার নেই।

এখন আপনি খুঁজে পেয়েছেন যে আপনাকে পয়েন্টার দ্বারা নির্দেশিত সেই অবজেক্টটি ক্রমিক করা দরকার। পয়েন্টারগুলির সমস্যা যে তারা প্রোগ্রামটিতে কেবল এটি ব্যবহারযোগ্য valid আপনি পয়েন্টারকে সিরিয়ালাইজ করতে পারবেন না, আপনাকে তাদের বস্তুগুলিতে ব্যবহার বন্ধ করা উচিত। পরিবর্তে অবজেক্ট পুল তৈরি করুন। এই অবজেক্ট পুলটি মূলত একটি গতিশীল অ্যারে যা "বাক্সগুলি" ধারণ করে। এই বাক্সগুলির একটি রেফারেন্স গণনা রয়েছে। অ-শূন্য রেফারেন্স গণনা একটি লাইভ অবজেক্টকে নির্দেশ করে, শূন্যটি একটি খালি স্লট নির্দেশ করে। তারপরে আপনি শেয়ার্ড_প্টারের সমান স্মার্ট পয়েন্টার তৈরি করেন যা পয়েন্টারটি বস্তুটিতে সঞ্চয় করে না, তবে সূচীতে অ্যারেতে থাকে। আপনাকে এমন একটি সূচকেও সম্মত করতে হবে যা নাল পয়েন্টারটিকে বোঝায়, যেমন। -1।

মূলত আমরা এখানে যা করেছি পয়েন্টারগুলি অ্যারে সূচকগুলির সাথে প্রতিস্থাপন করা হয়েছে। সিরিয়ালাইজ করার সময় আপনি যথারীতি এই অ্যারে সূচকটি সিরিয়াল করতে পারবেন। গন্তব্য সিস্টেমে কী জিনিসটি স্মৃতিতে থাকবে সে সম্পর্কে আপনাকে চিন্তা করার দরকার নেই। কেবল নিশ্চিত করুন যে তাদেরও একই বস্তু পুল রয়েছে।

সুতরাং আমাদের অবজেক্ট পুলগুলি সিরিয়ালাইজ করা দরকার। তবে কোনটি? আচ্ছা আপনি যখন কোনও অবজেক্টের গ্রাফকে সিরিয়ালাইজ করেন আপনি কেবল কোনও অবজেক্টকে সিরিয়ালাইজ করছেন না, আপনি একটি সম্পূর্ণ সিস্টেমকে সিরিয়ালাইজ করছেন। এর অর্থ সিস্টেমের ক্রমিকায়ন সিস্টেমের অংশ থেকে শুরু হওয়া উচিত নয়। Objects অবজেক্টগুলিকে সিস্টেমের বাকী অংশ নিয়ে চিন্তা করা উচিত নয়, তাদের কেবল অ্যারে সূচকগুলি সিরিয়ালাইজ করা দরকার এবং এটিই। আপনার সিস্টেমে সিরিয়ালাইজেশন রুটিন থাকা উচিত যা সিস্টেমটির সিরিয়ালাইজেশনকে অর্কেস্টেট করে এবং প্রাসঙ্গিক অবজেক্ট পুলগুলির মধ্য দিয়ে চলে এবং সেগুলি সমস্ত ক্রমিক করে তোলে।

প্রাপ্তির শেষে সমস্ত অ্যারের মধ্যে থাকা কোনও বস্তুর পছন্দসই অবজেক্ট গ্রাফটি পুনরায় তৈরি করা হয় এবং এর মধ্যে একটি বস্তুকে ডিসরিয়ালাইজ করা হয়।

ক্রিয়ালাইজিং ফাংশন পয়েন্টার

পয়েন্টার অবজেক্টে রাখবেন না। একটি স্ট্যাটিক অ্যারে থাকে যা এই ফাংশনগুলির পয়েন্টারগুলিকে ধারণ করে এবং অবজেক্টে সূচকটি সংরক্ষণ করে।

যেহেতু উভয় প্রোগ্রামই এই টেবিলটি তাদের শেল্ভগুলিতে সংকলিত করেছে, কেবলমাত্র সূচি ব্যবহার করে কাজ করা উচিত।

পলিমারফিক ধরণের সিরিয়ালিং করা

যেহেতু আমি বলেছি যে সিরিয়ালাইজযোগ্য প্রকারে আপনার পয়েন্টার এড়ানো উচিত এবং এর পরিবর্তে আপনার অ্যারে সূচকগুলি ব্যবহার করা উচিত, পলিমারফিজম কেবল কাজ করতে পারে না কারণ এর জন্য পয়েন্টার প্রয়োজন।

টাইপ ট্যাগ এবং ইউনিয়নগুলির সাথে আপনার এটি চারপাশে কাজ করা উচিত।

সংস্করণ

উপরের সমস্ত উপরে। আপনি সফ্টওয়্যার আন্তঃব্যবস্থার বিভিন্ন সংস্করণ চাইবেন।

এক্ষেত্রে প্রতিটি বিষয়বস্তু সংস্করণ নির্দেশ করতে তাদের সিরিয়ালাইজেশনের শুরুতে একটি সংস্করণ নম্বর লিখতে হবে।

অপরদিকে বস্তুটি লোড করার সময়, নতুন বস্তুগুলি পুরানো উপস্থাপনাগুলি পরিচালনা করতে সক্ষম হতে পারে তবে পুরানোগুলি নতুনকে হ্যান্ডেল করতে পারে না তাই তাদের এ সম্পর্কে একটি ব্যতিক্রম ছড়িয়ে দেওয়া উচিত।

প্রতিবার কিছু পরিবর্তন হওয়ার সাথে সাথে আপনার সংস্করণ নম্বরটি কাটাতে হবে।


সুতরাং এটি মোড়ানোর জন্য, সিরিয়ালাইজেশন জটিল হতে পারে। তবে ভাগ্যক্রমে আপনার প্রোগ্রামের সমস্ত কিছু সিরিয়ালাইজ করার দরকার নেই, বেশিরভাগ ক্ষেত্রে কেবল প্রোটোকল বার্তাগুলিই সিরিয়ালায়িত হয়, যা প্রায়শই পুরানো স্ট্রাইক থাকে। সুতরাং উপরে বর্ণিত জটিল কৌশলগুলি আপনার প্রয়োজন নেই।


4
ধন্যবাদ. এই উত্তরে সি ++ তে স্ট্রাকচার্ড ডেটা সিরিয়ালাইজ করার ক্ষেত্রে প্রাসঙ্গিক ধারণার একটি দুর্দান্ত ওভারভিউ রয়েছে।
শান

0

শেখার পথে আমি একটি সাধারণ সি ++ 11 সিরিয়ালাইজার লিখেছি। আমি অন্যান্য আরও ভারী ওজনের প্রস্তাবগুলির অনেকগুলি চেষ্টা করেছিলাম, তবে এমন কিছু চেয়েছিলাম যা আমি যখন বুঝতে পারি তখন এটি সর্বশেষতম জি ++ (যা সেরিয়ালের সাথে আমার জন্য ঘটেছিল; একটি সত্যই সুন্দর লাইব্রেরি তবে জটিল এবং আমি সঙ্কুচিত করতে পারি না) নিয়ে সংকলন করতে ব্যর্থ হলে আমি আসলে বুঝতে পারি সংকলকটি আপগ্রেড করার সময় যে ত্রুটিগুলি আপলোড করেছিল)) যাইহোক, এটি কেবল শিরোনাম এবং POD প্রকারগুলি, পাত্রে, মানচিত্রগুলি ইত্যাদি পরিচালনা করে ... কোনও সংস্করণ নয় এবং এটি কেবল একই আর্কাইভ থেকে ফাইলগুলি লোড করবে যা এটি সংরক্ষণ করা হয়েছিল।

https://github.com/goblinhack/simple-c-plus-plus-serializer

ব্যবহারের উদাহরণ:

#include "c_plus_plus_serializer.h"

static void serialize (std::ofstream out)
{
    char a = 42;
    unsigned short b = 65535;
    int c = 123456;
    float d = std::numeric_limits<float>::max();
    double e = std::numeric_limits<double>::max();
    std::string f("hello");

    out << bits(a) << bits(b) << bits(c) << bits(d);
    out << bits(e) << bits(f);
}

static void deserialize (std::ifstream in)
{
    char a;
    unsigned short b;
    int c;
    float d;
    double e;
    std::string f;

    in >> bits(a) >> bits(b) >> bits(c) >> bits(d);
    in >> bits(e) >> bits(f);
}

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.