স্ট্যান্ডার্ড :: টাইপ_ইনফো :: নামের ফলাফলটি অবিচ্ছেদ্য


97

আমি বর্তমানে কিছু লগিং কোড নিয়ে কাজ করছি যা অনুমান করা উচিত - অন্যান্য জিনিসের মধ্যে - কলিং ফাংশন সম্পর্কিত তথ্য মুদ্রণ করে। এটি তুলনামূলকভাবে সহজ হওয়া উচিত, স্ট্যান্ডার্ড সি ++ এর একটি type_infoবর্গ রয়েছে। এতে টাইপযুক্ত শ্রেণীর নাম / ফাংশন / ইত্যাদি রয়েছে। তবে এটি ম্যাঙ্গেলড। এটি খুব দরকারী নয়। অর্থাৎ typeid(std::vector<int>).name()রিটার্ন দেয় St6vectorIiSaIiEE

এ থেকে দরকারী কিছু উত্পাদন করার উপায় আছে কি? std::vector<int>উপরের উদাহরণের জন্য পছন্দ করুন । এটি যদি কেবলমাত্র টেম্পলেট শ্রেণীর জন্য কাজ করে তবে তাও ঠিক।

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

উত্তর:


119

এই প্রশ্ন / উত্তরটি যে মনোযোগ পেয়েছে এবং GManNickG এর কাছ থেকে মূল্যবান প্রতিক্রিয়া পেয়েছে আমি কোডটি কিছুটা সাফ করেছি। দুটি সংস্করণ দেওয়া হয়েছে: একটি সি ++ 11 বৈশিষ্ট্যযুক্ত এবং অন্যটি কেবল সি ++ 98 বৈশিষ্ট্যযুক্ত।

ফাইল টাইপ। Hpp

#ifndef TYPE_HPP
#define TYPE_HPP

#include <string>
#include <typeinfo>

std::string demangle(const char* name);

template <class T>
std::string type(const T& t) {

    return demangle(typeid(t).name());
}

#endif

ফাইল টাইপ। সি পি পি এ (সি ++ 11 প্রয়োজন)

#include "type.hpp"
#ifdef __GNUG__
#include <cstdlib>
#include <memory>
#include <cxxabi.h>

std::string demangle(const char* name) {

    int status = -4; // some arbitrary value to eliminate the compiler warning

    // enable c++11 by passing the flag -std=c++11 to g++
    std::unique_ptr<char, void(*)(void*)> res {
        abi::__cxa_demangle(name, NULL, NULL, &status),
        std::free
    };

    return (status==0) ? res.get() : name ;
}

#else

// does nothing if not g++
std::string demangle(const char* name) {
    return name;
}

#endif

ব্যবহার:

#include <iostream>
#include "type.hpp"

struct Base { virtual ~Base() {} };

struct Derived : public Base { };

int main() {

    Base* ptr_base = new Derived(); // Please use smart pointers in YOUR code!

    std::cout << "Type of ptr_base: " << type(ptr_base) << std::endl;

    std::cout << "Type of pointee: " << type(*ptr_base) << std::endl;

    delete ptr_base;
}

এটি প্রিন্ট করে:

পিটিআর_বাসের Base*
ধরণ : পয়েন্টির ধরণ:Derived

জি ++ 4.7.2, জি ++ 4.9.0 20140302 (পরীক্ষামূলক), ঝাঁকুনি ++ 3.4 (ট্রাঙ্ক 184647), লঙ্ঘন 3.5 (ট্রাঙ্ক 202594) লিনাক্স bit৪ বিট এবং জি ++ ৪. M.২ (মিংডব্লু, উইন 32 এক্সপি এসপি 2) এর সাথে পরীক্ষিত।

আপনি যদি সি ++ 11 বৈশিষ্ট্যগুলি ব্যবহার করতে না পারেন, তবে এটি এখানে সি ++ 98 এ কীভাবে করা যায় তা ফাইল টাইপ। সি পি পি এখন:

#include "type.hpp"
#ifdef __GNUG__
#include <cstdlib>
#include <memory>
#include <cxxabi.h>

struct handle {
    char* p;
    handle(char* ptr) : p(ptr) { }
    ~handle() { std::free(p); }
};

std::string demangle(const char* name) {

    int status = -4; // some arbitrary value to eliminate the compiler warning

    handle result( abi::__cxa_demangle(name, NULL, NULL, &status) );

    return (status==0) ? result.p : name ;
}

#else

// does nothing if not g++
std::string demangle(const char* name) {
    return name;
}

#endif


(সেপ্টেম্বর 8, 2013 থেকে আপডেট)

গৃহীত উত্তর (সেপ্টেম্বর 7, 2013 হিসাবে) , যখন কলটি abi::__cxa_demangle()সফল হয়, স্থানীয়কে একটি পয়েন্টার ফেরত দেয়, বরাদ্দ করা অ্যারের স্টোর ... আউট!
এছাড়াও মনে রাখবেন যে আপনি যদি বাফার সরবরাহ abi::__cxa_demangle()করেন তবে এটি গাদাতে বরাদ্দ দেওয়া হবে বলে ধরে নিন। স্ট্যাকের উপর বাফার বরাদ্দ করা একটি বাগ (gnu ডক থেকে): "যদি output_bufferযথেষ্ট দীর্ঘ না হয় তবে এটি ব্যবহার করে প্রসারিত হবে realloc।" স্ট্যাকের দিকে একটি পয়েন্টারে কল realloc()করছি ... আউট! (এছাড়াও ইগর স্কোচিনস্কির সদয় মন্তব্য দেখুন))

আপনি সহজেই এই বাগ উভয় যাচাই করতে পারেন: শুধু বাফারের আকার গৃহীত উত্তরে 1024 থেকে ছোট কিছু, উদাহরণস্বরূপ 16 কমাতে (7 সেপ্টেম্বর, 2013 হিসাবে), এবং এটি একটি নাম দিয়ে কিছু দিতে না 15 চেয়ে দীর্ঘতর (তাই realloc()হয় বলা হয় না )। তবুও, আপনার সিস্টেম এবং সংকলক অপ্টিমাইজেশনের উপর নির্ভর করে আউটপুটটি হবে: আবর্জনা / কিছুই নয় / প্রোগ্রাম ক্র্যাশ।
দ্বিতীয় ত্রুটি যাচাই করতে: বাফারের আকারটি 1 এ সেট করুন এবং যার নামটি 1 টির চেয়ে বেশি লম্বা এমন কিছু দিয়ে কল করুন। আপনি যখন এটি চালান, প্রোগ্রামটি অবশ্যই নিশ্চিতভাবে ক্র্যাশ হয়ে যায় যখন এটি realloc()স্ট্যাকের কোনও পয়েন্টার দিয়ে কল করার চেষ্টা করে ।


(27 ডিসেম্বর, 2010 এর পুরানো উত্তর)

গুরুত্বপূর্ণ পরিবর্তনগুলি করা KeithB এর কোড : বাফার পারেন malloc দ্বারা বরাদ্দ বা শূন্য হিসাবে নির্দিষ্ট করা হয়েছে। এটি স্ট্যাকের জন্য বরাদ্দ করবেন না।

সেই অবস্থানটিও পরীক্ষা করা বুদ্ধিমানের কাজ।

আমি খুঁজে পেতে ব্যর্থ HAVE_CXA_DEMANGLE। আমি পরীক্ষা করি __GNUG__যদিও এটি গ্যারান্টি দেয় না যে কোডটিও সংকলন করবে। কারও ভাল ধারণা আছে?

#include <cxxabi.h>

const string demangle(const char* name) {

    int status = -4;

    char* res = abi::__cxa_demangle(name, NULL, NULL, &status);

    const char* const demangled_name = (status==0)?res:name;

    string ret_val(demangled_name);

    free(res);

    return ret_val;
}

নোট করুন যে এটি প্রয়োজন #include <cxxabi.h>। অন্যথায় দুর্দান্ত কাজ, ধন্যবাদ।
জেটেরেস

4
দস্তাবেজগুলি থেকে : output_bufferমেমালির একটি অঞ্চল, * দৈর্ঘ্য বাইটের ম্যালোকের সাথে বরাদ্দ, যেখানে ডিমেংলেড নামটি সংরক্ষণ করা হয়। যদি আউটপুট_বাফার যথেষ্ট দীর্ঘ না হয় তবে এটি রিলোক ব্যবহার করে প্রসারিত হবে। আউটপুট_বফার পরিবর্তে নুল হতে পারে; সেক্ষেত্রে ডিমেংলড নামটি ম্যালোকের সাথে বরাদ্দ করা মেমরির অঞ্চলে স্থাপন করা হয়।
ইগোর স্কোচিনস্কি

4
@ ইগরস্কোচিনস্কি হ্যাঁ, আমার আগের মন্তব্যে একটি টাইপো রয়েছে তবে আমি এটি সম্পাদনা করতে পারি না। আমি যা লিখতে চেয়েছিলাম: "গতবার আমি পরীক্ষা করে দেখেছি abi::__cxa_demangleএটি গাদাতে বরাদ্দ দেওয়া হয়েছিল " "ডকটি অনুসন্ধান করার জন্য আপনাকে অনেক ধন্যবাদ!
আলী

4
নোট করুন যে প্রযুক্তিগতভাবে এটি ফাঁস হতে পারে যদি ret_valনির্মাণের সময় নিক্ষেপ করা হয়। এর বিরুদ্ধে রক্ষা করতে আপনি স্কোপ গার্ড ব্যবহার করতে পারেন।
GManNGG

4
যদি সম্ভবত std::unique_ptr<char, decltype(&std::free)>আপনার পয়েন্টারের স্বাক্ষর হিসাবে ব্যবহার করা আরও স্পষ্ট হয় ।
মাইন্ডভাইরাস

29

বুস্ট কোরটিতে একটি ডিমেনলার রয়েছে। চেকআউট কোর / demangle.hpp :

#include <boost/core/demangle.hpp>
#include <typeinfo>
#include <iostream>

template<class T> struct X
{
};

int main()
{
    char const * name = typeid( X<int> ).name();

    std::cout << name << std::endl; // prints 1XIiE
    std::cout << boost::core::demangle( name ) << std::endl; // prints X<int>
}

এটি মূলত কেবল একটি মোড়কের জন্য abi::__cxa_demangleযেমন আগে পরামর্শ দেওয়া হয়েছিল।


4
যদি বুস্টটি কোনও বিকল্প হয় তবে এটিই যাওয়ার সেরা উপায়!
hbobenicio

14

এটি আমরা ব্যবহার করি। HAVE_CXA_DEMANGLE কেবলমাত্র উপলভ্য থাকলে (কেবলমাত্র জিসিসির সাম্প্রতিক সংস্করণ) সেট করা আছে।

#ifdef HAVE_CXA_DEMANGLE
const char* demangle(const char* name)
{
   char buf[1024];
    unsigned int size=1024;
    int status;
    char* res = abi::__cxa_demangle (name,
                                 buf,
                                 &size,
                                 &status);
    return res;
  }
#else
const char* demangle(const char* name)
{
  return name;
}
#endif  

6
আপনাকে অন্তর্ভুক্ত করা দরকার #include <cxxabi.h>
ফুয়েনফুন্ডাচটজিগ 20'10

মজাদার. আমি HAVE_CXA_DEMANGLE সংজ্ঞায়িত __cxa_demangle সংজ্ঞায়িত করেছি
এম কে বি

@ ম্যাট আমি যা বলতে চাইছিলাম তা হ'ল অটোকনফের উপর ভিত্তি করে আমাদের বিল্ড সিস্টেমটি যদি পাওয়া যায় তবে কেবলমাত্র HAVE_CXA_DEMANGLE সেট করে।
কীথবি

19
সতর্কতা! উপরের কোডটি প্রোগ্রামটি ক্রাশ করার সম্ভাবনা রয়েছে। বাফার হয় হয় মলোক দ্বারা বরাদ্দ করতে হবে বা NULL হিসাবে নির্দিষ্ট করতে হবে। এটি স্ট্যাকের জন্য বরাদ্দ করবেন না। নীচে আমার কোড দেখুন।
আলী

নজর রাখুন, রেস
ন্যূন

9

এখানে, টাইপ_স্ট্রিংস hpp এ একবার দেখে নিন এটিতে একটি ফাংশন রয়েছে যা আপনি যা চান তা করে।

যদি আপনি কেবল একটি ডিমেংলিং সরঞ্জামের সন্ধান করেন, যা আপনি উদাহরণস্বরূপ লগ ফাইলটিতে দেখানো জিনিসগুলিকে ম্যাঙ্গেল করতে ব্যবহার করতে পারেন তবে একবার দেখুন c++filt, যা দ্বিখণ্ডিত সঙ্গে আসে। এটি সি ++ এবং জাভা প্রতীক নামগুলি ডিমেংল করতে পারে।


কেবল লক্ষণীয়, cxa_demange () কোডটি ব্যবহারের সাথে সংযুক্ত) এবং সিএক্স ++ ফিল্ট উভয়ই জিসিসি নির্দিষ্ট। এটি করার মতো কোনও পোর্টেবল উপায় নেই।
কিথবি

সি ++ ফিল্ট এটি কেটে না, সংকলন সময়ে আমার এই জিনিসগুলি (বা এটি বেশিরভাগের) প্রয়োজন, বেশিরভাগ ম্যাক্রোগুলির সাহায্যে করা হয়।
টার্মিনাস

4
টাইপ_স্ট্রিংস.পি.পি.-এর লিঙ্কটি ভাঙ্গা মনে হচ্ছে।
স্ট্যাকডক্রুকড

4
হাই @ গ্রেগরিপাকোস্ আপনার উপরের মন্তব্যে গিথুব লিঙ্কটি খুব ভাঙা মনে হচ্ছে :( চিয়ার্স
অলিব্রে

কেবলমাত্র একটি গুরুত্বপূর্ণ এফওয়াইআই: abi::__cxa_demangle()এবং এর থেকে <cxxabi.h> জিসিসি-নির্দিষ্ট নয় - এটি কেবলমাত্র অতীতের জিসিসি-হতে পারে, তবে এই পোস্টটির লেখার সময়টি <cxxabi.h>ছিল একটি প্রবেশপথের মান। সুতরাং যখন উত্তরটির কোড লিঙ্কটি ডিওআই ছিল, আমি এই ক্ষেত্রে ক্ল্যাংকে প্রথম শ্রেণির সহায়তা প্রদানের পক্ষে নিশ্চয়তা দিতে পারি ... ক্ল্যাংয়ের libcxxabiউত্স থেকে: qv, সম্পর্কিত ডেস্ক , ইমপ্ল , বিশাল পরীক্ষা: git.io/vRTBo , git.io/vRTBh , git.io/vRTRf - পরীক্ষার কোডের মন্তব্যগুলি ক্ল্যাং বাস্তবায়নটিকে আরও বেশি ডিমেংলিংয়ে সক্ষম বলে মনে করে , কোনওভাবে, বনাম জিসিসি।
fish2000

5

এটি বাস্তবায়ন সংজ্ঞায়িত, সুতরাং এটি এমন কিছু নয় যা পোর্টেবল হতে চলেছে। এমএসভিসি ++-তে, নাম () হ'ল অদৃশ্য নাম এবং সজ্জিত নামটি পেতে আপনাকে কাঁচা_নাম () দেখতে হবে।
এখানে অন্ধকারে কেবল একটি ছুরিকাঘাত, তবে জিসিসির অধীনে, আপনি ডেম্যাংলএইচএইচ দেখতে চাইতে পারেন


3

আমি একটি ম্যাক্রো নামেও পেয়েছি __PRETTY_FUNCTION__, যা কৌশলটি করে। এটি একটি সুন্দর ফাংশন নাম দেয় (পরিসংখ্যান :))। এই আমার প্রয়োজন ছিল।

অর্থাৎ এটি আমাকে নিম্নলিখিত দেয়:

virtual bool mutex::do_unlock()

তবে আমি মনে করি না এটি অন্যান্য সংকলকগুলিতে কাজ করে।


হ্যাঁ, PRETTY_FUNCTION জিসিসি নির্দিষ্ট।
গ্রেগ রজার্স

2

একটি সম্পূর্ণ সমাধান নয়, তবে আপনি ম্যাক্রোটির কিছু মানক (বা বহুল সমর্থিত) কী সংজ্ঞায়িত করেছেন তা আপনি দেখতে চাইতে পারেন। ম্যাক্রোগুলির ব্যবহার দেখার জন্য লগিং কোডে এটি সাধারণ:

__FUNCTION__
__FILE__
__LINE__

e.g.:

log(__FILE__, __LINE__, __FUNCTION__, mymessage);

4
PRETTY_FUNCTION উল্লেখ করার দরকার নেই
সিজারব

4
এটি আপনাকে কোডে কোথায় রয়েছে সে সম্পর্কে তথ্য দেবে। প্রশ্নটি যা জিজ্ঞাসা করছিল তা হ'ল স্ট্যান্ড :: ভেক্টরের মতো একটি প্রকারের সুন্দর নাম।
কিথবি

তিনি উল্লেখ করেছিলেন যে এটি ডিবাগিংয়ের জন্য ছিল, এবং আমি বলেছিলাম এটি কোনও সম্পূর্ণ সমাধান নয়। অন্যান্য ম্যাক্রো যেমন FUNCDNAME সজ্জিত নামটি ফিরিয়ে দেবে।
luke

প্রকৃতপক্ষে, প্রশ্নটি পুনরায় পড়া, এটি ছিল "আমি বর্তমানে কিছু লগিং কোড নিয়ে কাজ করছি যা ধারণা করা উচিত - অন্যান্য বিষয়গুলির মধ্যে - কলিং ফাংশন সম্পর্কিত তথ্য মুদ্রণ করে" " এইটা কাজ করে.
ম্যাক্স Lybbert

এটি সম্পূর্ণ নয়, যেহেতু আমি নামের জায়গাটি জানি না। এটি আমার কোডে প্রস্তুত। যা হোক ধন্যবাদ.
টার্মিনাস

2

আলীর সমাধান সম্পর্কে কিছুটা প্রকারভেদ। আপনি যদি চান কোডটি এখনও অনুরূপ হতে পারে

typeid(bla).name(),

পরিবর্তে এটি লেখা

Typeid(bla).name() (শুধুমাত্র প্রথম মূল অক্ষরে পৃথক)

তাহলে আপনি এতে আগ্রহী হতে পারেন:

ফাইল টাইপ। Hpp

#ifndef TYPE_HPP
#define TYPE_HPP

#include <string>
#include <typeinfo>

std::string demangle(const char* name);

/*
template <class T>
std::string type(const T& t) {

  return demangle(typeid(t).name());
}
*/

class Typeid {
 public:

  template <class T>
    Typeid(const T& t) : typ(typeid(t)) {}

  std::string name() { return demangle(typ.name()); }

 private:
  const std::type_info& typ;
};


#endif

টাইপ.cpp আলীর সমাধান হিসাবে একই থাকে


1

একবার দেখে এ নিন __cxa_demangleযা তোমাদের কোন জানতে পারেন cxxabi.h


আমি পেয়েছি, বার্তাটি আমি পেয়েছি তা অনুসারে এটি অবহেলা করা হয়েছে।
টার্মিনাস

সেই বার্তাটি আপনি কোথায় পেলেন? আমি কেবল এটি গুগল করেছি এবং এটি সমর্থনযোগ্য বলে মনে হচ্ছে, হ্রাস পাওয়ার কোনও প্রমাণ নেই।
আলী

হতে পারে এটি :: নেমস্পেসে হ্রাস পেয়েছে। Abi :: __ cxa_demangle ব্যবহার করুন এবং আপনি কোনও সতর্কতা পাবেন না। আপনি কোন জিসিসি ব্যবহার করছেন?
onitake

1
// KeithB's solution is good, but has one serious flaw in that unless buf is static
// it'll get trashed from the stack before it is returned in res - and will point who-knows-where
// Here's that problem fixed, but the code is still non-re-entrant and not thread-safe.
// Anyone care to improve it?

#include <cxxabi.h>

// todo: javadoc this properly
const char* demangle(const char* name)
{
    static char buf[1024];
    size_t size = sizeof(buf);
    int status;
    // todo:
    char* res = abi::__cxa_demangle (name,
                                 buf,
                                 &size,
                                 &status);
    buf[sizeof(buf) - 1] = 0; // I'd hope __cxa_demangle does this when the name is huge, but just in case.
    return res;
  }

11
সতর্কতা! বাফার হয় হয় মলোক দ্বারা বরাদ্দ করতে হবে বা NULL হিসাবে নির্দিষ্ট করতে হবে। এটি স্ট্যাকের জন্য বরাদ্দ করবেন না। নীচে আমার কোড দেখুন।
আলী

1

গৃহীত সমাধান [1] বেশিরভাগই ভাল কাজ করে। আমি কমপক্ষে একটি কেস পেয়েছি (এবং আমি এটিকে কর্নার কেস বলব না) যেখানে এটি আমার প্রত্যাশার প্রতিবেদন করে না ... রেফারেন্স সহ।

এই ক্ষেত্রে, আমি আরও একটি সমাধান পেয়েছি, নীচে পোস্ট করা।

সমস্যাযুক্ত কেস ( type[1] হিসাবে সংজ্ঞায়িত হিসাবে ব্যবহার করে ):

int i = 1;
cout << "Type of " << "i" << " is " << type(i) << endl;
int & ri = i;
cout << "Type of " << "ri" << " is " << type(ri) << endl;

উত্পাদন

Type of i is int
Type of ri is int

সমাধান (ব্যবহার করে type_name<decltype(obj)>(), নীচের কোডটি দেখুন):

cout << "Type of " << "i" << " is " << type_name<decltype(i)>() << endl;
cout << "Type of " << "ri" << " is " << type_name<decltype(ri)>() << endl;

উত্পাদন

Type of i is int
Type of ri is int&

পছন্দসই হিসাবে (কমপক্ষে আমার দ্বারা)

কোড । বিশেষায়নের সমস্যার কারণে এটি কোনও অন্তর্ভুক্ত শিরোনামে থাকতে হবে, আলাদাভাবে সংকলিত উত্সে নয়। উদাহরণস্বরূপ টেম্পলেট ফাংশনটির অপরিজ্ঞাত রেফারেন্স দেখুন ।

#ifndef _MSC_VER
#   include <cxxabi.h>
#endif
#include <memory>
#include <string>
#include <cstdlib>

template <class T>
std::string
type_name()
{
    typedef typename std::remove_reference<T>::type TR;
    std::unique_ptr<char, void(*)(void*)> own
           (
#ifndef _MSC_VER
                abi::__cxa_demangle(typeid(TR).name(), nullptr,
                                           nullptr, nullptr),
#else
                nullptr,
#endif
                std::free
           );
    std::string r = own != nullptr ? own.get() : typeid(TR).name();
    if (std::is_const<TR>::value)
        r += " const";
    if (std::is_volatile<TR>::value)
        r += " volatile";
    if (std::is_lvalue_reference<T>::value)
        r += "&";
    else if (std::is_rvalue_reference<T>::value)
        r += "&&";
    return r;
}

0

আমি সর্বদা টাইপ_ইনফোটি ব্যবহার করতে চেয়েছি, তবে আমি নিশ্চিত যে নামের () সদস্য ফাংশনের ফলাফলটি মানহীন এবং অগত্যা কোনও অর্থবোধী ফলাফলে রূপান্তরিত হতে পারে এমন কোনও কিছু ফেরত দেবে না।
আপনি যদি একটি সংকলককে আঁকড়ে ধরে থাকেন তবে সেখানে একটি সংকলক নির্দিষ্ট ফাংশন রয়েছে যা আপনি যা চান তা করবে। ডকুমেন্টেশন চেক করুন।


0

আলীর সমাধান অনুসরণ করে, এখানে সি ++ 11 টেম্প্লেটেড বিকল্পটি রয়েছে যা আমার ব্যবহারের জন্য সবচেয়ে ভাল কাজ করেছে।

// type.h
#include <cstdlib>
#include <memory>
#include <cxxabi.h>

template <typename T>
std::string demangle() {
  int status = -4;

  std::unique_ptr<char, void (*)(void*)> res{
      abi::__cxa_demangle(typeid(T).name(), NULL, NULL, &status), std::free};
  return (status == 0) ? res.get() : typeid(T).name();
}

ব্যবহার:

// main.cpp
#include <iostream>

namespace test {
    struct SomeStruct {};
}

int main()
{
    std::cout << demangle<double>() << std::endl;
    std::cout << demangle<const int&>() << std::endl;
    std::cout << demangle<test::SomeStruct>() << std::endl;

    return 0;
}

মুদ্রণ করবে:

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