সি ++ ম্যাক্রো কখন উপকারী? [বন্ধ]


177

সি প্রাক প্রসেসর যথার্থই হওয়াকে ভয় করেছে এবং সি ++ সম্প্রদায় থেকে দূরে থাকে। ইন-রেখাযুক্ত ফাংশন, কনসেটস এবং টেম্পলেটগুলি সাধারণত একটি এর একটি নিরাপদ এবং উচ্চতর বিকল্প #define

নিম্নলিখিত ম্যাক্রো:

#define SUCCEEDED(hr) ((HRESULT)(hr) >= 0)  

প্রকারের চেয়ে কোনওভাবেই সুরক্ষিত নয়:

inline bool succeeded(int hr) { return hr >= 0; }

তবে ম্যাক্রোগুলির তাদের স্থান রয়েছে, দয়া করে ম্যাক্রোগুলির জন্য আপনি যে ব্যবহারগুলি খুঁজে পেয়েছেন তার তালিকা করুন যা আপনি প্রিপ্রসেসর ছাড়াই করতে পারবেন না

দয়া করে প্রতিটি ব্যবহারের কেসগুলি একটি পৃথক উত্তরে রেখে দিন যাতে এটিতে ভোট দেওয়া যায় এবং আপনি যদি জেনে থাকেন যে এই উত্তরটির মন্তব্যে কীভাবে প্রিপ্রাইসেসর ছাড়াই কোনও উত্তর পেতে হয়।


আমি একবার ম্যাক্রোগুলিতে পূর্ণ সি ++ অ্যাপ্লিকেশন নিয়েছিলাম যা 45 মিনিট সময় নিতে তৈরি হয়েছিল, ম্যাক্রোগুলিকে ইনলাইন ফাংশনগুলির সাথে প্রতিস্থাপন করেছিল এবং বিল্ডটি 15 মিনিটেরও কম সময়ে নামিয়ে আনে।
এন্ডিয়ান


থ্রেডটি এমন প্রসঙ্গে রয়েছে যেখানে ম্যাক্রোগুলি উপকারী, এমন প্রসঙ্গে নয় যেগুলি তারা সাবমোটিমাল।
আন্ডারস্কোর_২২

উত্তর:


123

ডিবাগ কাজকর্মের জন্য চাদরে হিসেবে স্বয়ংক্রিয়ভাবে ভালো জিনিস পাস __FILE__, __LINE__ইত্যাদি:

#ifdef ( DEBUG )
#define M_DebugLog( msg )  std::cout << __FILE__ << ":" << __LINE__ << ": " << msg
#else
#define M_DebugLog( msg )
#endif

14
প্রকৃতপক্ষে, আসল স্নিপেট: << ফাইল ":" << ঠিক আছে, ফাইল একটি স্ট্রিং ধ্রুবক তৈরি করে, যা প্রসেসর দ্বারা একটি স্ট্রিংয়ে ":" দিয়ে সংযুক্ত করা হবে।
ফ্র্যাঙ্ক এস্কজারবা

12
এটি কেবলমাত্র কারণ প্রাক প্রসেসর প্রয়োজন __FILE__এবং __LINE__ এছাড়াও প্রাক প্রসেসর প্রয়োজন। আপনার কোডে এগুলি ব্যবহার করা প্রিপ্রোসেসরের জন্য সংক্রমণ ভেক্টরের মতো।
টেড

93

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

#define foreach(list, index) for(index = 0; index < list.size(); index++)

এবং এটি এইভাবে ব্যবহার করুন:

foreach(cookies, i)
    printf("Cookie: %s", cookies[i]);

সি ++ 11 সাল থেকে লুপের জন্য এটি পরিসর-ভিত্তিক দ্বারা ছাড়িয়ে যায়


6
+1 আপনি যদি কিছু হাস্যকর জটিল ইটারেটর সিনট্যাক্স ব্যবহার করছেন তবে ফোরচ স্টাইলের ম্যাক্রো লেখার ফলে আপনার কোডটি পড়া এবং বজায় রাখা আরও সহজ হবে। আমি এটা করেছি, এটা কাজ করে।
পোস্টফিউচারিস্ট

9
বেশিরভাগ মন্তব্য পুরোপুরি অপ্রাসঙ্গিকভাবে এই বিন্দুতে যে ম্যাক্রোগুলি সম্পূর্ণ কোডের পরিবর্তে কোড টুকরা হতে পারে। তবে নিটপিকিংয়ের জন্য আপনাকে ধন্যবাদ।
jdmichal

12
এটি সি নয় সি ++। আপনি যদি সি ++ করছেন, আপনার পুনরাবৃত্তকারী এবং স্টাডি :: ফর_ইচ ব্যবহার করা উচিত।
ক্রিশ

20
আমি একমত নই, ক্রিশ। ল্যাম্বডাসের আগে, for_eachএকটি বাজে জিনিস ছিল, কারণ প্রতিটি উপাদানটি কোডটি চালিত করার জন্য স্থানীয় ছিল না calling foreach, (এবং আমি BOOST_FOREACHহ্যান্ড-ঘূর্ণিত সমাধানের পরিবর্তে অত্যন্ত প্রস্তাব দিই) আসুন কোডটি পুনরাবৃত্তি সাইটের কাছে রাখুন, এটি আরও পাঠযোগ্য making এটি বলেছিল, একবার ল্যাম্বডা রোল আউট হয়ে গেলে, for_eachআবার একবার যেতে হবে।
GManNickG

8
এবং এটি লক্ষণীয় যে BOOST_FOREach নিজেই একটি ম্যাক্রো (তবে একটি খুব সুচিন্তিত একটি)
টাইলার ম্যাকহেনারি

59

শিরোলেখ ফাইল রক্ষীরা ম্যাক্রো প্রয়োজন।

ম্যাক্রোর প্রয়োজন এমন কি অন্য কোনও অঞ্চল রয়েছে ? অনেকগুলি (যদি থাকে) না।

ম্যাক্রো থেকে উপকৃত অন্য কোন পরিস্থিতি রয়েছে কি? হ্যাঁ!!!

আমি ম্যাক্রোগুলি ব্যবহার করি এমন একটি জায়গা খুব পুনরাবৃত্ত কোড সহ। উদাহরণস্বরূপ, অন্যান্য ইন্টারফেস (। নেট, সিওএম, পাইথন, ইত্যাদি ...) ব্যবহার করার জন্য সি ++ কোড মোড়ানোর সময়, আমার বিভিন্ন ধরণের ব্যতিক্রম ধরা দরকার। আমি এটি কীভাবে করব তা এখানে:

#define HANDLE_EXCEPTIONS \
catch (::mylib::exception& e) { \
    throw gcnew MyDotNetLib::Exception(e); \
} \
catch (::std::exception& e) { \
    throw gcnew MyDotNetLib::Exception(e, __LINE__, __FILE__); \
} \
catch (...) { \
    throw gcnew MyDotNetLib::UnknownException(__LINE__, __FILE__); \
}

আমাকে প্রতিটি রেপার ফাংশনে এই ক্যাচগুলি রাখতে হবে। প্রতিবার পুরো ক্যাচ ব্লকগুলি টাইপ করার পরিবর্তে আমি কেবল টাইপ করি:

void Foo()
{
    try {
        ::mylib::Foo()
    }
    HANDLE_EXCEPTIONS
}

এটি রক্ষণাবেক্ষণকে আরও সহজ করে তোলে। যদি আমাকে কখনও নতুন ব্যতিক্রম প্রকার যুক্ত করতে হয় তবে এটি যুক্ত করার জন্য আমার কেবলমাত্র একটি জায়গা রয়েছে।

এছাড়াও অন্যান্য দরকারী উদাহরণ রয়েছে: যার মধ্যে অনেকগুলি __FILE__এবং __LINE__প্রিপ্রসেসর ম্যাক্রোগুলি অন্তর্ভুক্ত ।

যাইহোক, সঠিকভাবে ব্যবহার করার সময় ম্যাক্রোগুলি খুব কার্যকর। ম্যাক্রোগগুলি মন্দ নয় - তাদের অপব্যবহারটি মন্দ।


7
বেশিরভাগ সংকলক #pragma onceআজকাল সমর্থন করে, তাই আমি সন্দেহ করি যে প্রহরীরা সত্যই প্রয়োজনীয়
1800 তথ্য

13
আপনি যদি কেবলমাত্র বেশিরভাগ ;-) পরিবর্তে সমস্ত সংকলকগুলির জন্য লিখছেন তবে সেগুলি হ'ল
স্টিভ জেসোপ

30
সুতরাং পোর্টেবল, স্ট্যান্ডার্ড প্রিপ্রোসেসর কার্যকারিতা পরিবর্তে আপনি প্রিপ্রসেসর ব্যবহার এড়াতে একটি প্রিপ্রোসেসর এক্সটেনশন ব্যবহার করার পরামর্শ দিচ্ছেন? আমার কাছে একরকম হাস্যকর মনে হচ্ছে।
লোগান ক্যাপাল্ডো

#pragma onceঅনেকগুলি সাধারণ বিল্ড সিস্টেমে বিরতি।
মাইলস রাউট

4
সেখানে যে যে ম্যাক্রো প্রয়োজন হয় না একটি সমাধান পাওয়া যাবে: void handleExceptions(){ try { throw } catch (::mylib::exception& e) {....} catch (::std::exception& e) {...} ... }। এবং ফাংশনের দিকে:void Foo(){ try {::mylib::Foo() } catch (...) {handleExceptions(); } }
মাইকেএমবি

51

অধিকাংশ ক্ষেত্রে:

  1. প্রহরী অন্তর্ভুক্ত
  2. শর্তসাপেক্ষ সংকলন
  3. প্রতিবেদন করা (পূর্বনির্ধারিত ম্যাক্রোগুলির মতো __LINE__এবং __FILE__)
  4. (খুব কম) পুনরাবৃত্ত কোড নিদর্শনগুলি সদৃশ করা।
  5. আপনার প্রতিযোগী কোডে।

কীভাবে 5 নম্বর অনুধাবন করা যায় তার জন্য কিছু সহায়তার সন্ধান করছেন আপনি কি আমাকে কোনও সমাধানের দিকে পরিচালিত করতে পারেন?
সর্বোচ্চ

50

সংস্থাপকগুলির মধ্যে পার্থক্যের বিষয়গুলি কাটিয়ে উঠতে শর্তসাপেক্ষ সংকলনের ভিতরে:

#ifdef ARE_WE_ON_WIN32
#define close(parm1)            _close (parm1)
#define rmdir(parm1)            _rmdir (parm1)
#define mkdir(parm1, parm2)     _mkdir (parm1)
#define access(parm1, parm2)    _access(parm1, parm2)
#define create(parm1, parm2)    _creat (parm1, parm2)
#define unlink(parm1)           _unlink(parm1)
#endif

12
সি ++ এ, ইনলাইন ফাংশনগুলির ব্যবহারের মাধ্যমে এটি পাওয়া যেতে পারে: <কোড> # আইডিডিআরই_ডব্লিউআইএন_উইএন 32 <br> ইনলাইন ইনট ক্লোজ (ইনট আই) {রিটার্ন ক্লোজ (আই); } <br> #endif </code>
প্যাসেসারবাল

2
এটি # সংজ্ঞায়িতগুলি সরিয়ে দেয়, তবে #ifdef এবং #endif নয়। যাইহোক, আমি আপনার সাথে একমত।
গর্পিক

19
কখনও কখনও নিম্ন কেস ম্যাক্রো সংজ্ঞায়িত করুন। ম্যাক্রোস ফাংশনগুলিতে পরিবর্তন করা আমার দুঃস্বপ্ন (আপনাকে ধন্যবাদ মাইক্রোসফ্ট)। প্রথম উদাহরণে সেরা উদাহরণ। অনেক লাইব্রেরির closeফাংশন বা পদ্ধতি রয়েছে। তারপরে আপনি যখন এই লাইব্রেরির শিরোনাম এবং এই ম্যাক্রোর সাথে শিরকটি অন্তর্ভুক্ত করবেন তখন আপনার বড় সমস্যা রয়েছে, আপনি লাইব্রেরি এপিআই ব্যবহার করতে পারবেন না।
মেরেক আর

অ্যান্ড্রুস্টেইন, @ প্যাসেরেবলের পরামর্শের চেয়ে আপনি কি এই প্রসঙ্গে ম্যাক্রোগুলির ব্যবহারের কোনও উপকার দেখতে পাচ্ছেন? যদি তা না হয় তবে মনে হয় ম্যাক্রোগুলি আসলে কৃতজ্ঞ।
einpoklum

1
#ifdef WE_ARE_ON_WIN32plz :)
অরবিটে

38

আপনি যখন কোনও ভাবের বাইরে স্ট্রিং তৈরি করতে চান, তবে এর সর্বোত্তম উদাহরণ হ'ল assert( একটি স্ট্রিংয়ের #xমান ঘুরিয়ে দেয় x)।

#define ASSERT_THROW(condition) \
if (!(condition)) \
     throw std::exception(#condition " is false");

5
কেবল একটি নিটপিক, তবে আমি ব্যক্তিগতভাবে সেমিকোলনটি ছেড়ে দেব।
মাইকেল

10
আমি একমত, আসলে আমি এটি একটি (in)) করার সময় করব (মিথ্যা) (অন্যথায় হাইজ্যাকিং রোধ করতে) তবে আমি এটিকে সহজ রাখতে চাই।
মোটি 18

33

স্ট্রিং ধ্রুবকগুলি কখনও কখনও ম্যাক্রো হিসাবে আরও বেশি সংজ্ঞায়িত হয় কারণ আপনি স্ট্রিং লিটারেলের সাথে আরও বেশি কিছু করতে পারেন const char *

উদাহরণস্বরূপ স্ট্রিং লিটারেলগুলি সহজেই সংক্ষেপিত হতে পারে

#define BASE_HKEY "Software\\Microsoft\\Internet Explorer\\"
// Now we can concat with other literals
RegOpenKey(HKEY_CURRENT_USER, BASE_HKEY "Settings", &settings);
RegOpenKey(HKEY_CURRENT_USER, BASE_HKEY "TypedURLs", &URLs);

যদি একটি const char *ব্যবহার করা হয় তবে রানটাইমের সময় কিছুটা স্ট্রিং ক্লাস সংক্ষেপণ সম্পাদন করতে ব্যবহৃত হত:

const char* BaseHkey = "Software\\Microsoft\\Internet Explorer\\";
RegOpenKey(HKEY_CURRENT_USER, (string(BaseHkey) + "Settings").c_str(), &settings);
RegOpenKey(HKEY_CURRENT_USER, (string(BaseHkey) + "TypedURLs").c_str(), &URLs);

2
সি ++ এ, আমি এটিকে সবচেয়ে গুরুত্বপূর্ণ অংশ হিসাবে বিবেচনা করব (রক্ষীদের অন্তর্ভুক্ত ব্যতীত)। সংকলন-সময়ের স্ট্রিং প্রসেসিংয়ের জন্য আমাদের কাছে ম্যাক্রোগুলি সত্যই সেরা জিনিস। এটি এমন একটি বৈশিষ্ট্য যা আমি আশা করি আমরা সি ++ 11++ এ পেয়ে যাব
ডেভিড স্টোন

1
এই পরিস্থিতিটি আমাকে সি # তে ম্যাক্রোগুলির জন্য আকাঙ্ক্ষা করতে পরিচালিত করেছিল।
রাউলিং

2
আমি চাই আমি এই +42 করতে পারে। একটি খুব গুরুত্বপূর্ণ, যদিও প্রায়শই স্ট্রিং লেটারেলের দিকটি মনে থাকে না।
ড্যানিয়েল কামিল কোজার

24

আপনি যখন কোনও ফাংশনে প্রোগ্রাম প্রবাহ ( return, breakএবং continue) কোডটি পরিবর্তন করতে চান তখন ফাংশনে প্রকৃতপক্ষে অন্তর্ভুক্ত কোডের চেয়ে আলাদা আচরণ করে।

#define ASSERT_RETURN(condition, ret_val) \
if (!(condition)) { \
    assert(false && #condition); \
    return ret_val; }

// should really be in a do { } while(false) but that's another discussion.

একটি ব্যতিক্রম নিক্ষেপ করা আমার কাছে আরও ভাল বিকল্পের মতো বলে মনে হচ্ছে।
einpoklum

যখন পাইথন সি লেখার (++,) এক্সটেনশন, ব্যতিক্রম ব্যতিক্রম স্ট্রিং সেটিং, তারপর ফিরে প্রচারিত হয় -1বা NULL। সুতরাং একটি ম্যাক্রো সেখানে বয়লারপ্লেট কোডকে ব্যাপকভাবে হ্রাস করতে পারে।
কালো_প্প্পিডোগ

20

স্পষ্টত রক্ষী অন্তর্ভুক্ত

#ifndef MYHEADER_H
#define MYHEADER_H

...

#endif

17

আপনি নিয়মিত ফাংশন কল ব্যবহার করে ফাংশন কল আর্গুমেন্টের শর্ট সার্কিট করতে পারবেন না। উদাহরণ স্বরূপ:

#define andm(a, b) (a) && (b)

bool andf(bool a, bool b) { return a && b; }

andm(x, y) // short circuits the operator so if x is false, y would not be evaluated
andf(x, y) // y will always be evaluated

3
হতে পারে আরও সাধারণ বিষয়: ফাংশনগুলি তাদের যুক্তিগুলি একবারে মূল্যায়ন করে। ম্যাক্রোগুলি আরও বেশি বা কয়েকবার যুক্তির মূল্যায়ন করতে পারে।
স্টিভ জেসোপ

@ [গ্রেগ রজার্স] সমস্ত ম্যাক্রো প্রিপ্রসেসরটি হ'ল বিকল্প পাঠ্য। একবার আপনি এটি বুঝতে পারলে, এটি সম্পর্কে আর কোনও রহস্য থাকা উচিত নয়।
1800 তথ্য

ফাংশনটি বলার আগে আপনি মূল্যায়নকে জোর করে পরিবর্তে অস্থির করে অ্যান্ডফ্ল্যাম করে সমান আচরণ পেতে পারেন। আপনি নিজের জন্য চেষ্টা না করে আপনি যা বলেছিলেন তা সত্য বলে আমি বুঝতে পারি না। মজাদার.
গ্রেগ রজার্স

কোনও টেম্পলেট দিয়ে আপনি কীভাবে এটি করতে পারেন?
1800 তথ্য 21

6
ফাংশন স্টাইলের ম্যাক্রোর পিছনে সংক্ষিপ্ত-সার্কিট ক্রিয়াকলাপগুলি লুকিয়ে রাখা এমন একটি জিনিস যা আমি সত্যিই উত্পাদন কোডে দেখতে চাই না।
মাইকএমবি

17

আসুন আমরা বলি যে আমরা হেডার গার্ডগুলির মতো সুস্পষ্ট বিষয়গুলি এড়িয়ে যাব।

কখনও কখনও, আপনি এমন কোড তৈরি করতে চান যা প্রম্পম্পাইলার দ্বারা অনুলিপি / আটকানো দরকার:

#define RAISE_ERROR_STL(p_strMessage)                                          \
do                                                                             \
{                                                                              \
   try                                                                         \
   {                                                                           \
      std::tstringstream strBuffer ;                                           \
      strBuffer << p_strMessage ;                                              \
      strMessage = strBuffer.str() ;                                           \
      raiseSomeAlert(__FILE__, __FUNCSIG__, __LINE__, strBuffer.str().c_str()) \
   }                                                                           \
   catch(...){}                                                                \
   {                                                                           \
   }                                                                           \
}                                                                              \
while(false)

যা আপনাকে এটি কোড করতে সক্ষম করে:

RAISE_ERROR_STL("Hello... The following values " << i << " and " << j << " are wrong") ;

এবং এই জাতীয় বার্তা তৈরি করতে পারে:

Error Raised:
====================================
File : MyFile.cpp, line 225
Function : MyFunction(int, double)
Message : "Hello... The following values 23 and 12 are wrong"

নোট করুন যে ম্যাক্রোগুলির সাথে টেমপ্লেটগুলি মিশ্রিত করা আরও ভাল ফলাফলের দিকে নিয়ে যেতে পারে (অর্থাত্ তাদের পরিবর্তনশীল নামের সাথে মানগুলি স্বয়ংক্রিয়ভাবে উত্পন্ন করে)

অন্যান্য সময়, উদাহরণস্বরূপ, ডিবাগ তথ্য উত্পন্ন করার জন্য আপনার কিছু কোডের __FILE__ এবং / অথবা __LINE__ প্রয়োজন। নিম্নলিখিত ভিজ্যুয়াল সি ++ এর জন্য একটি ক্লাসিক:

#define WRNG_PRIVATE_STR2(z) #z
#define WRNG_PRIVATE_STR1(x) WRNG_PRIVATE_STR2(x)
#define WRNG __FILE__ "("WRNG_PRIVATE_STR1(__LINE__)") : ------------ : "

নিম্নলিখিত কোড হিসাবে:

#pragma message(WRNG "Hello World")

এটি বার্তা উত্পন্ন করে:

C:\my_project\my_cpp_file.cpp (225) : ------------ Hello World

অন্য সময়ে, আপনাকে কোনও সম্পত্তি এবং তার জন্য সেটটার তৈরি করার মতো # এবং ## কনটেনটেশন অপারেটরগুলি ব্যবহার করে কোড জেনারেট করতে হবে (এটি বেশ সীমিত ক্ষেত্রে, এটির মাধ্যমে)।

অন্য সময়, আপনি কোনও ফাংশনের মাধ্যমে ব্যবহার করলে সংকলন না করে কোড উত্পন্ন করবেন, যেমন:

#define MY_TRY      try{
#define MY_CATCH    } catch(...) {
#define MY_END_TRY  }

যা হিসাবে ব্যবহার করা যেতে পারে

MY_TRY
   doSomethingDangerous() ;
MY_CATCH
   tryToRecoverEvenWithoutMeaningfullInfo() ;
   damnThoseMacros() ;
MY_END_TRY

(তবুও, আমি কেবল এই জাতীয় কোডটি একবারে সঠিকভাবে ব্যবহার করা দেখেছি )

সর্বশেষে, তবে কম নয়, বিখ্যাত boost::foreach!!!

#include <string>
#include <iostream>
#include <boost/foreach.hpp>

int main()
{
    std::string hello( "Hello, world!" );

    BOOST_FOREACH( char ch, hello )
    {
        std::cout << ch;
    }

    return 0;
}

(দ্রষ্টব্য: কোড কপি / বুস্ট হোমপেজ থেকে আটকানো)

যা (আইএমএইচও) এর চেয়ে ভাল std::for_each

সুতরাং, ম্যাক্রোগুলি সর্বদা দরকারী কারণ তারা সাধারণ সংকলক নিয়মের বাইরে। তবে আমি দেখতে পেলাম যে বেশিরভাগ সময় আমি একটি দেখি, সেগুলি কার্যকরভাবে সি কোডের অবশেষে যথাযথ সি ++ তে কখনও অনুবাদ হয় না।


1
কম্পাইলার যা করতে পারে না তার জন্য কেবল সিপিপি ব্যবহার করুন। উদাহরণস্বরূপ, RAISE_ERROR_STL কেবল ফাইল, লাইন এবং ফাংশন স্বাক্ষর নির্ধারণের জন্য সিপিপি ব্যবহার করা উচিত এবং এগুলি একটি ফাংশনে (সম্ভবত ইনলাইন) যা পাসগুলি করে তা পাস করে।
রেইনার ব্লুম

দয়া করে আপনার উত্তরটি সি ++ 11 প্রতিবিম্বিত করতে এবং @ রেইনারব্লমের মন্তব্যে ঠিকানার জন্য আপডেট করুন।
einpoklum

@ রাইনার ব্লোম: আমরা সম্মত হই। RAISE_ERROR_STL ম্যাক্রো প্রাক-সি ++ 11, সুতরাং সেই প্রসঙ্গে এটি পুরোপুরি ন্যায়সঙ্গত। আমার বোঝাপড়া (তবে আমি সেই নির্দিষ্ট বৈশিষ্ট্যগুলির সাথে মোকাবিলা করার উপলক্ষটি কখনই পাইনি) হ'ল আপনি সমস্যাটিকে আরও মার্জিতভাবে সমাধানের জন্য মডার্ন সি ++ এ ভ্যারিয়েডিক টেম্পলেট (বা ম্যাক্রো?) ব্যবহার করতে পারেন।
পেরেেসবাল

@ আইনপোকলুম: "দয়া করে আপনার উত্তরটি সি ++ 11 প্রতিবিম্বিত করার জন্য আপডেট করুন এবং রেইনারব্লমের মন্তব্যকে সম্বোধন করুন" ন: :-)। । । আমি বিশ্বাস করি, সর্বোপরি, আমি ম্যাক্রোগুলির প্রয়োজনীয়তা হ্রাস বা অপসারণের সাথে বিকল্প বাস্তবায়ন সহ আধুনিক সি ++ এর জন্য একটি বিভাগ যুক্ত করব, তবে মূল বক্তব্যটি দাঁড়ায়: ম্যাক্রোরা কুশ্রী এবং মন্দ, কিন্তু যখন আপনার কিছু করার দরকার হয় তখন সংকলক বুঝতে পারে না , আপনি ম্যাক্রোর মাধ্যমে এটি করেন।
প্যারেসেবল

এমনকি সি ++ 11 এর সাথেও, আপনার ম্যাক্রো যা কিছু করে তা কোনও ফাংশন করার জন্য রেখে দেওয়া যেতে পারে: #include <sstream> #include <iostream> using namespace std; void trace(char const * file, int line, ostream & o) { cerr<<file<<":"<<line<<": "<< static_cast<ostringstream & >(o).str().c_str()<<endl; } struct Oss { ostringstream s; ostringstream & lval() { return s; } }; #define TRACE(ostreamstuff) trace(__FILE__, __LINE__, Oss().lval()<<ostreamstuff) int main() { TRACE("Hello " << 123); return 0; }এইভাবে, ম্যাক্রোটি আরও সংক্ষিপ্ত।
রেইনার ব্লুম

16

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


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

15

সি প্রিপ্রোসেসরকে ভয় পাওয়া যেমন ভাসমান বাল্বকে ভয় করা ঠিক তেমনি আমরা ফ্লুরোসেন্ট বাল্ব পাই। হ্যাঁ, পূর্বেরটি হতে পারে {বিদ্যুৎ | প্রোগ্রামার সময় - অদক্ষ। হ্যাঁ, আপনি তাদের দ্বারা (আক্ষরিক) পোড়াতে পারেন burned আপনি যদি এটি সঠিকভাবে পরিচালনা করেন তবে তারা কাজটি পেতে পারে।

আপনি যখন এমবেডেড সিস্টেমগুলি প্রোগ্রাম করেন, তখন সি একমাত্র বিকল্প হিসাবে ফর্ম এসেম্ব্লার হিসাবে ব্যবহৃত হয়। ডেস্কটপে সি ++ সহ প্রোগ্রামিং করার পরে এবং আরও ছোট, এম্বেড করা লক্ষ্যগুলিতে স্যুইচ করার পরে, আপনি এতগুলি খালি সি বৈশিষ্ট্যগুলির (ম্যাক্রোগুলি অন্তর্ভুক্ত) "অসচ্ছলতা" সম্পর্কে চিন্তা করা বন্ধ করতে শিখেন এবং কেবল সেইগুলি থেকে পেতে পারেন এমন সর্বোত্তম এবং সুরক্ষিত ব্যবহারগুলি বের করার চেষ্টা করছেন বৈশিষ্ট্যগুলিও উপস্থিত রয়েছে।

আলেকজান্ডার স্টেপানভ বলেছেন :

আমরা যখন সি ++ এ প্রোগ্রাম করি তখন এর সি heritageতিহ্য নিয়ে আমাদের লজ্জিত হওয়া উচিত নয়, তবে এটির পুরো ব্যবহার করা উচিত। সি ++ সহ কেবলমাত্র সমস্যাগুলি এবং এমনকি সি এর সাথে একমাত্র সমস্যাগুলি তখনই উদ্ভূত হয় যখন তারা নিজেরাই নিজের যুক্তির সাথে সামঞ্জস্য না করে।


আমি মনে করি এটিই ভুল দৃষ্টিভঙ্গি। আপনি "সঠিকভাবে এটি পরিচালনা করতে" শিখতে পারার অর্থ এই নয় যে এটি কারও জন্য সময় এবং প্রচেষ্টার পক্ষে মূল্যবান।
নিল জি

9

আমরা আমাদের কিউএ অবকাঠামোতে স্বয়ংক্রিয় লগ ফাইল স্ক্যানারগুলির সাথে, তথ্য সমৃদ্ধ ব্যতিক্রম নিক্ষেপ, ধরা __FILE__এবং __LINE__লগিংয়ে ডায়াগনস্টিক উদ্দেশ্যে ব্যবহার করি ।

উদাহরণস্বরূপ, একটি নিক্ষেপণ OUR_OWN_THROWবিবরণ সহ, এই ব্যতিক্রমের জন্য ব্যতিক্রম প্রকার এবং কনস্ট্রাক্টর পরামিতিগুলির সাথে একটি নিক্ষেপণ ম্যাক্রো ব্যবহার করা যেতে পারে। এটার মত:

OUR_OWN_THROW(InvalidOperationException, (L"Uninitialized foo!"));

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


9

কোড পুনরাবৃত্তি।

প্রিপ্রসেসর লাইব্রেরিটি বাড়ানোর জন্য একবার নজর দিন , এটি এক ধরণের মেটা-মেটা-প্রোগ্রামিং। বিষয়-> অনুপ্রেরণায় আপনি একটি ভাল উদাহরণ খুঁজে পেতে পারেন।


আমি প্রায় সবাই, সব না থাকলে কেস - কোড পুনরাবৃত্তি ফাংশন কল দিয়ে এড়ানো যেতে পারে।
einpoklum

@ আইনপোকলুম: আমি একমত নই। লিঙ্কটি একবার দেখুন
রাগেরো তুররা

9

প্রিপ্রোসেসর (ম্যাক্রোস) ব্যবহার করে কিছু খুব উন্নত এবং দরকারী স্টাফ তৈরি করা যেতে পারে, যা আপনি টেমপ্লেটগুলি সহ সি ++ "ল্যাঙ্গুয়েজ কনস্ট্রাক্টস" ব্যবহার করতে পারবেন না।

উদাহরণ:

সি সনাক্তকারী এবং একটি স্ট্রিং উভয়ই কিছু তৈরি করা

এনএম টাইপের ভেরিয়েবলগুলি সি তে স্ট্রিং হিসাবে ব্যবহার করার সহজ উপায়

প্রিপ্রসেসর মেটাপোগ্র্যামিং বুস্ট করুন


তৃতীয় লিঙ্কটি ভাঙা ফাই
রবিন হার্টল্যান্ড

আরও ভাল করে বোঝার জন্য একবার দেখুন stdio.hএবং sal.hফাইল করুন vc12
এলশান

7

আমি মাঝেমধ্যে ম্যাক্রোগুলি ব্যবহার করি যাতে আমি তথ্য এক জায়গায় সংজ্ঞায়িত করতে পারি, তবে কোডের বিভিন্ন অংশে এটি বিভিন্ন উপায়ে ব্যবহার করি। এটা কেবল সামান্য দুষ্ট :)

উদাহরণস্বরূপ, "ফিল্ড_লিস্ট। H" তে:

/*
 * List of fields, names and values.
 */
FIELD(EXAMPLE1, "first example", 10)
FIELD(EXAMPLE2, "second example", 96)
FIELD(ANOTHER, "more stuff", 32)
...
#undef FIELD

তারপরে সর্বজনীন এনামের জন্য এটি কেবল নামটি ব্যবহারের জন্য সংজ্ঞায়িত করা যেতে পারে:

#define FIELD(name, desc, value) FIELD_ ## name,

typedef field_ {

#include "field_list.h"

    FIELD_MAX

} field_en;

এবং একটি বেসরকারী init ফাংশনে, সমস্ত ক্ষেত্র ডেটা সহ একটি সারণী তৈরি করতে ব্যবহার করা যেতে পারে:

#define FIELD(name, desc, value) \
    table[FIELD_ ## name].desc = desc; \
    table[FIELD_ ## name].value = value;

#include "field_list.h"

1
দ্রষ্টব্য: অনুরূপ কৌশলটি পৃথক অন্তর্ভুক্ত না করেও প্রয়োগ করা যেতে পারে। দেখুন: স্ট্যাকওভারফ্লো / সিকিউশনস
সুমা

6

একটি সাধারণ ব্যবহার হ'ল সংকলন পরিবেশ সনাক্তকরণের জন্য, ক্রস-প্ল্যাটফর্ম বিকাশের জন্য আপনি লিনাক্সের জন্য একটি কোডের সেট লিখতে পারেন, বলুন এবং অন্যটি উইন্ডোজের জন্য যখন কোনও ক্রস প্ল্যাটফর্ম লাইব্রেরি ইতিমধ্যে আপনার উদ্দেশ্যে উপস্থিত না থাকে।

সুতরাং, একটি মোটামুটি উদাহরণে একটি ক্রস প্ল্যাটফর্মের মিটেক্স থাকতে পারে

void lock()
{
    #ifdef WIN32
    EnterCriticalSection(...)
    #endif
    #ifdef POSIX
    pthread_mutex_lock(...)
    #endif
}

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


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

আমি দ্বিতীয় যে. যদি আপনি সেই উদ্দেশ্যে ম্যাক্রোগুলি ব্যবহার শুরু করেন তবে কোডটি খুব দ্রুত পাঠযোগ্য হয়ে উঠতে পারে
নেমানজা ত্রিফুনোভিচ

6

কিছুটা এইরকম

void debugAssert(bool val, const char* file, int lineNumber);
#define assert(x) debugAssert(x,__FILE__,__LINE__);

যাতে আপনি যেমন উদাহরণস্বরূপ করতে পারেন

assert(n == true);

এবং যদি এন মিথ্যা হয় তবে উত্স ফাইলের নাম এবং আপনার লগতে মুদ্রিত সমস্যার লাইন নম্বর পান।

আপনি যদি কোনও সাধারণ ফাংশন কল ব্যবহার করেন তবে

void assert(bool val);

ম্যাক্রোর পরিবর্তে, আপনি যা কিছু পেতে পারেন তা হ'ল লগতে মুদ্রিত আপনার আসক্তি ফাংশনের লাইন নম্বরটি, যা কম দরকারী হবে।


স্ট্যান্ডার্ড লাইব্রেরি বাস্তবায়ন যখন ম্যাক্রোর মাধ্যমে ইতিমধ্যে সরবরাহ <cassert>করে assert(), তখন ফাইলটি / লাইন / ফাংশন সম্পর্কিত তথ্য নষ্ট করে দেয় কেন আপনি চাকাটিকে পুনরায় সঞ্চার করবেন ? (সমস্ত বাস্তবায়নে আমি যাইহোক, দেখেছি)
আন্ডারস্কোর_২১

4
#define ARRAY_SIZE(arr) (sizeof arr / sizeof arr[0])

একটি বর্তমান থ্রেডে আলোচিত 'পছন্দসই' টেম্পলেট সমাধানের বিপরীতে, আপনি এটি একটি ধ্রুবক প্রকাশ হিসাবে ব্যবহার করতে পারেন:

char src[23];
int dest[ARRAY_SIZE(src)];

2
এই একটি নিরাপদ ভাবে টেমপ্লেট সঙ্গে কাজ করা যেতে পারে (যা যদি একটি অ্যারের তুলনায় বরং একটি পয়েন্টার পাস কম্পাইল হবে না) stackoverflow.com/questions/720077/calculating-size-of-an-array/...
Motti

1
এখন যেহেতু আমাদের C ++ 11 এ কনটেক্সপ্রস রয়েছে, নিরাপদ (ম্যাক্রোবিহীন) সংস্করণটি ধ্রুবক অভিব্যক্তিতেও ব্যবহার করা যেতে পারে। template<typename T, std::size_t size> constexpr std::size_t array_size(T const (&)[size]) { return size; }
ডেভিড স্টোন

3

আপনি ডিবাগিং এবং ইউনিট পরীক্ষার দৃশ্যের সাহায্যে # ডেফাইনগুলি ব্যবহার করতে পারেন। উদাহরণস্বরূপ, মেমরি ফাংশনগুলির বিশেষ লগিং রূপগুলি তৈরি করুন এবং একটি বিশেষ মেমলোগ_প্রেইনক্লুড.এল তৈরি করুন:

#define malloc memlog_malloc
#define calloc memlog calloc
#define free memlog_free

আপনার কোডটি ব্যবহার করে সংকলন করুন:

gcc -Imemlog_preinclude.h ...

চূড়ান্ত চিত্রটিতে আপনার মেমলোগ.ওএর একটি লিঙ্ক। আপনি এখন লগিং উদ্দেশ্যে, বা ইউনিট পরীক্ষার জন্য বরাদ্দ ব্যর্থতা অনুকরণ করতে malloc, ইত্যাদি নিয়ন্ত্রণ করুন।


3

যখন আপনি সংকলক / ওএস / হার্ডওয়্যার নির্দিষ্ট আচরণের মাধ্যমে সংকলন সময়ে সিদ্ধান্ত নিচ্ছেন।

এটি আপনাকে কমপিলার / ওএস / হার্ডওয়্যার নির্দিষ্ট বৈশিষ্ট্যগুলিতে আপনার ইন্টারফেস তৈরি করতে দেয়।

#if defined(MY_OS1) && defined(MY_HARDWARE1)
#define   MY_ACTION(a,b,c)      doSothing_OS1HW1(a,b,c);}
#elif define(MY_OS1) && defined(MY_HARDWARE2)
#define   MY_ACTION(a,b,c)      doSomthing_OS1HW2(a,b,c);}
#elif define(MY_SUPER_OS)
          /* On this hardware it is a null operation */
#define   MY_ACTION(a,b,c)
#else
#error  "PLEASE DEFINE MY_ACTION() for this Compiler/OS/HArdware configuration"
#endif

3

আমি সহজেই ব্যতিক্রমগুলি সংজ্ঞায়িত করতে ম্যাক্রোগুলি ব্যবহার করি:

DEF_EXCEPTION(RessourceNotFound, "Ressource not found")

যেখানে DEF_EXCEPTION

#define DEF_EXCEPTION(A, B) class A : public exception\
  {\
  public:\
    virtual const char* what() const throw()\
    {\
      return B;\
    };\
  }\

2

সংকলকরা আপনার অনুরোধটিকে ইনলাইন করতে অস্বীকার করতে পারে।

ম্যাক্রোদের সর্বদা তাদের স্থান থাকবে।

আমি দরকারী কিছু ডিবাগ ট্রেসিংয়ের জন্য # ডেফাইন DEBUG হ'ল - কোনও সমস্যা ডিবাগ করার সময় আপনি এটি 1 টি রেখে যেতে পারেন (বা এটি পুরো বিকাশের চক্র চলাকালীনও ছেড়ে দিতে পারেন) তারপরে শিপিংয়ের সময়টি বন্ধ করে দিন।


10
যদি সংকলক আপনার অনুরোধটিকে ইনলাইন করতে অস্বীকার করে তবে এটির খুব ভাল কারণ হতে পারে। একটি ভাল সংকলক আপনার চেয়ে সঠিকভাবে ইনলাইন করাতে ভাল হবে এবং একটি খারাপ এটি আপনাকে এর চেয়ে আরও বেশি পারফরম্যান্স সমস্যা দেয়।
ডেভিড থর্নলি

টুইটার কিছু সংকলক কেবল বকাবকি হয়।
মাইলস রাউটে

2

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

#define dbgmsg(_FORMAT, ...)  if((debugmsg_flag  & 0x00000001) || (debugmsg_flag & 0x80000000))     { log_dbgmsg(_FORMAT, __VA_ARGS__);  }

লগ ফাংশনগুলিতে VA_ARGS এর কারণে, এটি এই জাতীয় ম্যাক্রোর পক্ষে ভাল ঘটনা ছিল।

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

ম্যাক্রো (গুলি) হিসাবে সংজ্ঞায়িত:

#define SECURITY_CHECK(lRequiredSecRoles) if(!DoSecurityCheck(lRequiredSecRoles, #lRequiredSecRoles, true)) return
#define SECURITY_CHECK_QUIET(lRequiredSecRoles) (DoSecurityCheck(lRequiredSecRoles, #lRequiredSecRoles, false))

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

SECURITY_CHECK(ROLE_BUSINESS_INFORMATION_STEWARD | ROLE_WORKER_ADMINISTRATOR);

LRESULT CAddPerson1::OnWizardNext() 
{
   if(m_Role.GetItemData(m_Role.GetCurSel()) == parent->ROLE_EMPLOYEE) {
      SECURITY_CHECK(ROLE_WORKER_ADMINISTRATOR | ROLE_BUSINESS_INFORMATION_STEWARD ) -1;
   } else if(m_Role.GetItemData(m_Role.GetCurSel()) == parent->ROLE_CONTINGENT) {
      SECURITY_CHECK(ROLE_CONTINGENT_WORKER_ADMINISTRATOR | ROLE_BUSINESS_INFORMATION_STEWARD | ROLE_WORKER_ADMINISTRATOR) -1;
   }
...

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


2

তবুও আরেক ফোরচ ম্যাক্রো। টি: টাইপ, সি: ধারক, i: পুনরুক্তি

#define foreach(T, c, i) for(T::iterator i=(c).begin(); i!=(c).end(); ++i)
#define foreach_const(T, c, i) for(T::const_iterator i=(c).begin(); i!=(c).end(); ++i)

ব্যবহার (ধারণাটি প্রদর্শন, বাস্তব নয়):

void MultiplyEveryElementInList(std::list<int>& ints, int mul)
{
    foreach(std::list<int>, ints, i)
        (*i) *= mul;
}

int GetSumOfList(const std::list<int>& ints)
{
    int ret = 0;
    foreach_const(std::list<int>, ints, i)
        ret += *i;
    return ret;
}

আরও ভাল বাস্তবায়ন উপলব্ধ: গুগল "BOOST_FOREach"

ভাল নিবন্ধগুলি উপলভ্য: শর্তাধীন প্রেম: পূর্ববর্তী রেডাক্স (এরিক নাইবারার) http://www.artima.com/cppsource/foreach.html


2

হতে পারে ম্যাক্রোগুলির গ্রেটসের ব্যবহার প্ল্যাটফর্ম-স্বতন্ত্র বিকাশে রয়েছে। প্রকারের অসঙ্গতিগুলির ক্ষেত্রে চিন্তা করুন - ম্যাক্রোগুলির সাহায্যে আপনি কেবল বিভিন্ন শিরোনামের ফাইলগুলি ব্যবহার করতে পারেন - যেমন: --WIN_TYPES.H

typedef ...some struct

--POSIX_TYPES.h

typedef ...some another struct

--program.h

#ifdef WIN32
#define TYPES_H "WINTYPES.H"
#else 
#define TYPES_H "POSIX_TYPES.H"
#endif

#include TYPES_H

এটিকে অন্যান্য উপায়ে প্রয়োগ করার চেয়ে আমার পাঠের চেয়ে অনেক বেশি পাঠযোগ্য।


2

দেখে মনে হচ্ছে VA_ARGS এর এখনও পর্যন্ত অপ্রত্যক্ষভাবে উল্লেখ করা হয়েছে:

জেনেরিক সি ++ 03 কোড লেখার সময় এবং আপনার (জেনেরিক) প্যারামিটারগুলির একটি পরিবর্তনশীল সংখ্যার প্রয়োজন হয়, আপনি কোনও টেমপ্লেটের পরিবর্তে ম্যাক্রো ব্যবহার করতে পারেন।

#define CALL_RETURN_WRAPPER(FnType, FName, ...)          \
  if( FnType theFunction = get_op_from_name(FName) ) {   \
    return theFunction(__VA_ARGS__);                     \
  } else {                                               \
    throw invalid_function_name(FName);                  \
  }                                                      \
/**/

দ্রষ্টব্য: সাধারণভাবে, চেক / থ্রো নামটিও অনুমানের get_op_from_nameফাংশনে অন্তর্ভুক্ত হতে পারে । এইটা শুধুমাত্র একটা উদাহরণ. ভিএ_আরজিএস কলকে ঘিরে অন্য জেনেরিক কোড থাকতে পারে।

একবার আমরা C ++ 11 এর সাথে বৈকল্পিক টেম্পলেটগুলি পেয়ে গেলে আমরা এই "সঠিকভাবে" কোনও টেমপ্লেট দিয়ে সমাধান করতে পারি।


1

আমি মনে করি এই কৌশলটি প্রিপ্রোসেসরের একটি চতুর ব্যবহার যা কোনও ফাংশন দিয়ে অনুকরণ করা যায় না:

#define COMMENT COMMENT_SLASH(/)
#define COMMENT_SLASH(s) /##s

#if defined _DEBUG
#define DEBUG_ONLY
#else
#define DEBUG_ONLY COMMENT
#endif

তারপরে আপনি এটি ব্যবহার করতে পারেন:

cout <<"Hello, World!" <<endl;
DEBUG_ONLY cout <<"This is outputed only in debug mode" <<endl;

আপনি একটি RELEASE_ONLY ম্যাক্রোও সংজ্ঞায়িত করতে পারেন।


2
এই কৌশলটি মান অনুযায়ী কাজ করে না। এটি প্রিপ্রোসেসরের মাধ্যমে একটি মন্তব্য মার্কার তৈরি করার চেষ্টা করে, তবে প্রিপ্রসেসর চালানোর আগে মন্তব্যগুলি অপসারণ করা উচিত। একটি কনফর্মিং সংকলক এখানে একটি সিনট্যাক্স ত্রুটি সৃষ্টি করবে।
ডেভিড থর্নলি

2
দুঃখিত ডেভিড তবে সংকলকটিতে অবশ্যই মন্তব্য অপসারণের একটি দ্বিতীয় অনুলিপি থাকতে হবে।
জোশুয়া

ডিবাগিং পতাকাটিকে একটি বিশ্বব্যাপী কনস্ট বোল করা, এবং এর মতো কোড ব্যবহার করা আরও সহজ: যদি (ডিবাগ) কোট << "..."; - ম্যাক্রোর দরকার নেই!
স্টিফান মনোভ

@ স্টেফান: সত্যই, আমি এখন এটি করি। কোনও ক্ষেত্রে শালীন সংকলক কোনও কোড জেনারেট করে না যদি ডিবাগ সে ক্ষেত্রে মিথ্যা থাকে।
ম্যাথিউ পাগ

1

আপনি করতে পারেন #defineকম্পাইলার কমান্ড লাইন ধ্রুবক ব্যবহার -Dবা /Dবিকল্প। একাধিক প্ল্যাটফর্মের জন্য একই সফটওয়্যারটি ক্রস-সংকলন করার সময় এটি প্রায়শই দরকারী কারণ আপনি আপনার মেকফিলগুলি প্রতিটি প্ল্যাটফর্মের জন্য কী ধ্রুবককে সংজ্ঞায়িত করতে পারেন তা নিয়ন্ত্রণ করতে পারেন।

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