সি ++ ম্যাক্রো সহ ptionচ্ছিক পরামিতি


105

সি ++ ম্যাক্রোসের সাথে alচ্ছিক পরামিতি পাওয়ার কোনও উপায় আছে কি? একরকম ওভারলোডিং খুব ভাল হবে।


1
একই সি জন্য: stackoverflow.com/questions/11761703/... একই হতে হবে যেহেতু preprocessors হয় মূলত একই: stackoverflow.com/questions/5085533/...
সিরো Santilli郝海东冠状病六四事件法轮功

হতে পারে ফাংশন ওভারলোডস, ডিফল্ট প্যারামিটারগুলি, ভেরিয়াদিক টেম্পলেট বা সম্ভবত নামকরণ করা প্যারামিটারের আইডিয়ামগুলি আপনি যা খুঁজছেন তা
হ'ল

দয়া করে আপনার নির্বাচিত উত্তরটি উচ্চ-উত্সাহিতদের সাথে প্রকৃত সমাধানগুলি আপডেট করুন, নিম্ন-উর্ধ্বমুখী একটি উক্তিটি নয়No you can't
অ্যালবার্ট রেনশওয়া

উত্তর:


155

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

enum
{
    plain = 0,
    bold = 1,
    italic = 2
};

void PrintString(const char* message, int size, int style)
{
}

#define PRINT_STRING_1_ARGS(message)              PrintString(message, 0, 0)
#define PRINT_STRING_2_ARGS(message, size)        PrintString(message, size, 0)
#define PRINT_STRING_3_ARGS(message, size, style) PrintString(message, size, style)

#define GET_4TH_ARG(arg1, arg2, arg3, arg4, ...) arg4
#define PRINT_STRING_MACRO_CHOOSER(...) \
    GET_4TH_ARG(__VA_ARGS__, PRINT_STRING_3_ARGS, \
                PRINT_STRING_2_ARGS, PRINT_STRING_1_ARGS, )

#define PRINT_STRING(...) PRINT_STRING_MACRO_CHOOSER(__VA_ARGS__)(__VA_ARGS__)

int main(int argc, char * const argv[])
{
    PRINT_STRING("Hello, World!");
    PRINT_STRING("Hello, World!", 18);
    PRINT_STRING("Hello, World!", 18, bold);

    return 0;
}

এটি ম্যাক্রোর কলকারীকে সহজ করে তোলে তবে লেখক নয়।


1
এটি বেশ দুর্দান্ত, তবে আমি মনে করি না যে আমি কেবল PRINT_STRING করলে এটি কাজ করবে work সেক্ষেত্রে একটি ডিফল্ট প্রিন্ট আউট হবে না (এবং এটি আসলে আমি ব্যবহার করতে চাইছি)। সত্যই শীতল জন্য এখনও +1।
সেনোক

2
জিসিসিতে আমার জন্য কাজ করে (এবং এটি খুব চালাক!) :) তবে ভিজ্যুয়াল স্টুডিওতে আমার পক্ষে কাজ করে না :-(
টিম গ্রেডওয়েল

3
@ টিমগ্রাডওয়েল - এটি এমএসভিসি সংকলকটিতে থাকা একটি বাগের কারণে যা তারা স্বীকার করেছে তবে প্রায় এক দশকে স্থির হয়নি। যাইহোক, workaround উপলব্ধ
BeeOnRope

চালাক, তবে push GET_4 তম_আরজি'-তে আপনি যে 'পুশ আউট' জিনিস চালাচ্ছেন তার কারণে variচ্ছিক বৈকল্পিক ম্যাক্রো যুক্তিগুলির পক্ষে কাজ করে না।
searchengine27

এটি কি PRINT_STRING_MACRO_CHOOSERপ্রয়োজন? আমি কি সরাসরি এর অভ্যন্তরীণ শরীরের সাথে প্রতিস্থাপন করতে এবং এই পুরো জিনিসটি দিয়ে কল করতে পারি (__VA_ARGS__)?
হার্গোট

85

তার উত্তরের জন্য ডেরেক লেডবেটারের প্রতি অত্যন্ত শ্রদ্ধার সাথে - এবং একটি পুরানো প্রশ্ন পুনরুদ্ধারের জন্য ক্ষমাপ্রার্থী।

এটা কি করছেন এবং preceed করার ক্ষমতা অন্য কোথাও গোছগাছ একটি বোঝার পথ __VA_ARGS__সঙ্গে ##অনুমতি দেওয়া আমাকে একটা প্রকরণ নিয়ে আসা ...

// The multiple macros that you would need anyway [as per: Crazy Eddie]
#define XXX_0()                     <code for no arguments> 
#define XXX_1(A)                    <code for one argument> 
#define XXX_2(A,B)                  <code for two arguments> 
#define XXX_3(A,B,C)                <code for three arguments> 
#define XXX_4(A,B,C,D)              <code for four arguments>  

// The interim macro that simply strips the excess and ends up with the required macro
#define XXX_X(x,A,B,C,D,FUNC, ...)  FUNC  

// The macro that the programmer uses 
#define XXX(...)                    XXX_X(,##__VA_ARGS__,\
                                          XXX_4(__VA_ARGS__),\
                                          XXX_3(__VA_ARGS__),\
                                          XXX_2(__VA_ARGS__),\
                                          XXX_1(__VA_ARGS__),\
                                          XXX_0(__VA_ARGS__)\
                                         ) 

আমার মতো অ-বিশেষজ্ঞ যারা উত্তরটি নিয়ে হোঁচট খায়, তবে এটি কীভাবে কাজ করে তা বেশ দেখতে পাচ্ছেন না, আমি নিম্নলিখিত কোডটি দিয়ে শুরু করে প্রকৃত প্রক্রিয়াজাতকরণের মধ্য দিয়ে যাব ...

XXX();
XXX(1); 
XXX(1,2); 
XXX(1,2,3); 
XXX(1,2,3,4); 
XXX(1,2,3,4,5);      // Not actually valid, but included to show the process 

হয়ে ...

XXX_X(, XXX_4(), XXX_3(),  XXX_2(),    XXX_1(),      XXX_0()         );
XXX_X(, 1,       XXX_4(1), XXX_3(1),   XXX_2(1),     XXX_1(1),       XXX_0(1)          );
XXX_X(, 1,       2,        XXX_4(1,2), XXX_3(1,2),   XXX_2(1,2),     XXX_1(1,2),       XXX_0(1,2)        );
XXX_X(, 1,       2,        3,          XXX_4(1,2,3), XXX_3(1,2,3),   XXX_2(1,2,3),     XXX_1(1,2,3),     XXX_0(1,2,3)      );
XXX_X(, 1,       2,        3,          4,            XXX_4(1,2,3,4), XXX_3(1,2,3,4),   XXX_2(1,2,3,4),   XXX_1(1,2,3,4),   XXX_0(1,2,3,4)    );
XXX_X(, 1,       2,        3,          4,            5,              XXX_4(1,2,3,4,5), XXX_3(1,2,3,4,5), XXX_2(1,2,3,4,5), XXX_1(1,2,3,4,5), XXX_0(1,2,3,4,5) );

যা হয়ে যায় মাত্র ষষ্ঠ যুক্তি ...

XXX_0(); 
XXX_1(1); 
XXX_2(1,2); 
XXX_3(1,2,3); 
XXX_4(1,2,3,4); 
5; 

PS: একটি সংকলন ত্রুটি পেতে XXX_0 এর জন্য # ডেফাইনটি সরান [উদাহরণস্বরূপ: যদি কোনও নো-আর্গুমেন্ট বিকল্প অনুমোদিত না হয়]।

পিপিএস: অবৈধ পরিস্থিতিগুলি (যেমন: 5) এমন কিছু হতে পারে যা প্রোগ্রামারকে আরও পরিষ্কার সংকলন ত্রুটি দেয়!

পিপিপিএস: আমি বিশেষজ্ঞ নই, তাই মন্তব্য শুনে ভাল লাগল (ভাল, খারাপ বা অন্য)!


3
আপনি যদি একটি নির্বাচিত যুক্তি যা ম্যাক্রোর নাম হিসাবে স্ট্রিংয়ে # (পাউন্ড সাইন) ব্যবহার করে রূপান্তর করে এবং এর প্রথম এন অক্ষরকে প্রত্যাশিত উপসর্গের সাথে তুলনা করেন এবং যদি কোনও মিল না থাকে তবে একটি তথ্যপূর্ণ মুদ্রণ করতে পারলে আপনি একটি পরিষ্কার সংকলন ত্রুটি পেতে পারেন ত্রুটি.
আতুরস্যামস

1
বাহ, আমি জানি না এটি কাজ করে কিনা তবে এটি অন্তত খুব সৃজনশীল!
সীমিত প্রায়শ্চিত্ত

4
প্রথম যুক্তিটি সর্বদা খালি কেন? কেন নাকিসুরে কথা আমরা শুধু বর্জন এটা: XXX_X(,##__VA_ARGS__,` ... XXX_X (অন্যান্য XXX_4 (), XXX_3 এ (), XXX_2 এ (), XXX_1 আপনাকে (), XXX_0 ()); `
রহমান

2
খালি প্রথম যুক্তি (কমা) গুরুত্বপূর্ণ। ## __ VA_ARGS__ যদি এটি কমা দ্বারা পূর্ববর্তী হয় – যদি ## __ VA_ARGS__ কিছুতেই প্রসারিত না হয় তবে এটি কমাটি সরিয়ে দেয়। আপনি এটি "হয়ে যান ..." উদাহরণে দেখতে পাবেন প্রথম হিসাবে (কোনও যুক্তি নেই) লাইনে কেবলমাত্র 6 টি প্যারামিটার রয়েছে তবে বাকীগুলি 7 পায় This এই কৌশলটি নিশ্চিত করে যে কোনও আর্গুমেন্টের পরিস্থিতি কাজ করে না
ডেভিড Sorkovsky

@ এরিক - এটি মাইক্রোসফ্ট সংকলকগুলিতে একটি বাগের কারণে, তবে আপনি এই প্রশ্নটি কাজের সমাধানের জন্য দেখতে পারেন ।
BeeOnRope

31

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

সাইডেনোট হিসাবে: সি ++ এ সাধারণত ম্যাক্রো থেকে যতটা সম্ভব দূরে সরিয়ে নেওয়া ভাল অভ্যাস হিসাবে বিবেচিত হয়। আপনার যদি এর মতো বৈশিষ্ট্যগুলির প্রয়োজন হয় তবে আপনি ম্যাক্রোকে অতিরিক্ত ব্যবহার করছেন এমন একটি ভাল সুযোগ রয়েছে।


4
মনে রাখবেন যে ম্যাক্রোগুলিকে "ওভারলোড" করা অসম্ভব যে কারণ তাদের কোনও সহজাত প্রকার নেই don't ম্যাক্রোগুলি কেবল প্রসারিত হয়।
এম কে 12

2
যদিও আমি যতটা সম্ভব ম্যাক্রোগুলি ব্যবহার করি, আমি দেখতে পেলাম যে ট্রেস আউটপুট মাধ্যমে ডিবাগিং এর মতো __FILE__এবং এই জাতীয় জিনিসগুলির সাথে কিছুটা সহজ হয়ে যায় __LINE__...
ক্রিশ্চিয়ান সেভেরিন

একটি ভাল উত্তর না। : এটা ভাল উত্তর stackoverflow.com/q/27049491/893406
v.oddou

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

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

26

সবচেয়ে বড় সম্মান সঙ্গে ডেরেক Ledbetter, , ডেভিড Sorkovsky , Syphorlate তাদের উত্তরের জন্য, একসঙ্গে খালি ম্যাক্রো আর্গুমেন্ট সনাক্ত করতে প্রতিভাশালী পদ্ধতি সঙ্গে জেনস Gustedt

https://gustedt.wordpress.com/2010/06/08/detect-empty-macro-arguments/

অবশেষে আমি এমন কিছু নিয়ে আসলাম যা সমস্ত কৌশলকে সংযুক্ত করে, যাতে সমাধান

  1. ফাংশন ওভারলোডিং অর্জনের জন্য কেবলমাত্র স্ট্যান্ডার্ড সি 99 ম্যাক্রোগুলি ব্যবহার করে , কোনও জিসিসি / সিএলএং / এমএসভিসি এক্সটেনশন জড়িত নেই (অর্থাত্, , ##__VA_ARGS__জিসিসি / সিএলএং- এর নির্দিষ্ট অভিব্যক্তি দ্বারা কমা গিলে ফেলা, এবং ##__VA_ARGS__এমএসভিসির জন্য নিখুঁত গিলে )। সুতরাং নিখরচায় --std=c99আপনার কম্পাইলারের কাছে যদি আপনি চান =) পাস করুন
  2. জন্য কাজ করে শূন্য যুক্তি , সেইসাথে আর্গুমেন্ট সীমাহীন সংখ্যক , আপনি এটি আরও আপনার প্রয়োজন অনুসারে প্রসারিত যদি
  3. যুক্তিসঙ্গতভাবে ক্রস প্ল্যাটফর্ম কাজ করে , কমপক্ষে এর জন্য পরীক্ষিত

    • জিএনইউ / লিনাক্স + জিসিসি (সেন্টস 7.0 x86_64-তে জিসিসি 4.9.2)
    • জিএনইউ / লিনাক্স + সিএলএং / এলএলভিএম , (সেন্টোস .0.০ x86_64 এ ক্লাং / এলএলভিএম 3.5.0)
    • ওএস এক্স + এক্সকোড , (ওএস এক্স ইয়োসেমাইট 10.10.1 এ এক্সকোড 6.1.1)
    • উইন্ডোজ + ভিজ্যুয়াল স্টুডিও , (উইন্ডোজ 7 এসপি 1 64 বিটগুলিতে ভিজ্যুয়াল স্টুডিও 2013 আপডেট 4)

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

এটি কিভাবে যায় তা এখানে। প্রথম ব্যবহারকারী দৃশ্যমান ওভারলোড "ফাংশন" define, আমি এটা নামে create, এবং এর সাথে সম্পর্কিত প্রকৃত ফাংশন সংজ্ঞা realCreate, এবং আর্গুমেন্ট অন্য নম্বর দিয়ে ম্যাক্রো সংজ্ঞা CREATE_2, CREATE_1, CREATE_0, নিচে দেখানো হিসাবে:

#define create(...) MACRO_CHOOSER(__VA_ARGS__)(__VA_ARGS__)

void realCreate(int x, int y)
{
  printf("(%d, %d)\n", x, y);
}

#define CREATE_2(x, y) realCreate(x, y)
#define CREATE_1(x) CREATE_2(x, 0)
#define CREATE_0() CREATE_1(0)

MACRO_CHOOSER(__VA_ARGS__)অংশ পরিণামে ম্যাক্রো সংজ্ঞা নামের সমাধান করা, এবং দ্বিতীয় (__VA_ARGS__)অংশ তাদের প্যারামিটার তালিকা গঠিত। করার জন্য একটি ব্যবহারকারীর কল তাই create(10)করতে সমাধান করা CREATE_1(10), CREATE_1অংশ থেকে আসে MACRO_CHOOSER(__VA_ARGS__), এবং (10)অংশ দ্বিতীয় থেকে আসে(__VA_ARGS__)

এই MACRO_CHOOSERকৌশলটি ব্যবহার করে __VA_ARGS__যা শূন্য থাকলে নিচের অভিব্যক্তিটি প্রিপ্রসেসর দ্বারা বৈধ ম্যাক্রো কলটিতে সংযুক্ত করা হয়:

NO_ARG_EXPANDER __VA_ARGS__ ()  // simply shrinks to NO_ARG_EXPANDER()

Ingeniusly, আমরা এই ফলস্বরূপ ম্যাক্রো কল হিসাবে সংজ্ঞায়িত করতে পারি

#define NO_ARG_EXPANDER() ,,CREATE_0

দুটি কমা নোট করুন, তাদের শীঘ্রই ব্যাখ্যা করা হবে। পরবর্তী দরকারী ম্যাক্রো হয়

#define MACRO_CHOOSER(...) CHOOSE_FROM_ARG_COUNT(NO_ARG_EXPANDER __VA_ARGS__ ())

তাই কল

create();
create(10);
create(20, 20);

আসলে প্রসারিত হয়

CHOOSE_FROM_ARG_COUNT(,,CREATE_0)();
CHOOSE_FROM_ARG_COUNT(NO_ARG_EXPANDER 10 ())(10);
CHOOSE_FROM_ARG_COUNT(NO_ARG_EXPANDER 20, 20 ())(20, 20);

ম্যাক্রোর নামটি যেমন প্রস্তাবিত হয়, আমরা পরে আর্গুমেন্টের সংখ্যা গণনা করব। এখানে আরও একটি কৌশল আসে: প্রিপ্রসেসর কেবল সাধারণ পাঠ্য প্রতিস্থাপন করে। এটি ম্যক্রো কলের আর্গুমেন্টগুলির সংখ্যাটিকে অনুগ্রহ করে কেবল প্যারেন্টেসিসের মধ্যে দেখতে পাওয়া কমা সংখ্যা থেকে তা অনুমান করে। কমা দ্বারা পৃথক প্রকৃত "তর্কগুলি" বৈধ বাক্য গঠন করার প্রয়োজন হয় না। এগুলি যে কোনও পাঠ্য হতে পারে। এটি বলার জন্য, উপরের উদাহরণে, NO_ARG_EXPANDER 10 ()মধ্য কলটির জন্য 1 টি আর্গুমেন্ট হিসাবে গণ্য করা হয় NO_ARG_EXPANDER 20এবং20 () যথাক্রমে নীচের কলটির জন্য 2 টি আর্গুমেন্ট হিসাবে গণ্য করা হয়।

যদি আমরা নিম্নলিখিত সহায়িকার ম্যাক্রোগুলি তাদের আরও প্রসারিত করতে ব্যবহার করি

##define CHOOSE_FROM_ARG_COUNT(...) \
  FUNC_RECOMPOSER((__VA_ARGS__, CREATE_2, CREATE_1, ))
#define FUNC_RECOMPOSER(argsWithParentheses) \
  FUNC_CHOOSER argsWithParentheses

চিহ্ন ,পর CREATE_1একটি কাজ-অ্যারাউন্ড জিসিসি / ঝনঝন, একটি (মিথ্যা ধনাত্মক) ত্রুটি এই বলে যে দমন হয় ISO C99 requires rest arguments to be usedযখন ক্ষণস্থায়ী -pedanticআপনার কম্পাইলার করতে। FUNC_RECOMPOSERMSVC জন্য কাজ প্রায় হয়, অথবা এটি সঠিকভাবে ম্যাক্রো কল প্রথম বন্ধনী ভিতরে আর্গুমেন্টের সংখ্যা (অর্থাত, কমা) গণনা করতে পারবে না। ফলাফল আরও সমাধান করা হয়

FUNC_CHOOSER (,,CREATE_0, CREATE_2, CREATE_1, )();
FUNC_CHOOSER (NO_ARG_EXPANDER 10 (), CREATE_2, CREATE_1, )(10);
FUNC_CHOOSER (NO_ARG_EXPANDER 20, 20 (), CREATE_2, CREATE_1, )(20, 20);

আপনি যেমন agগল চোখের সাথে দেখে থাকতে পারেন, আমাদের কেবলমাত্র শেষ পদক্ষেপটি হ'ল ম্যাক্রো সংস্করণের নামগুলি বেছে নেওয়ার জন্য একটি স্ট্যান্ডার্ড আর্গুমেন্ট কাউন্টিং ট্রিক নিয়োগ করা:

#define FUNC_CHOOSER(_f1, _f2, _f3, ...) _f3

যা ফলাফলগুলি সমাধান করে

CREATE_0();
CREATE_1(10);
CREATE_2(20, 20);

এবং অবশ্যই আমাদের কাঙ্ক্ষিত, আসল ফাংশন কল দেয়:

realCreate(0, 0);
realCreate(10, 10);
realCreate(20, 20);

আরও ভাল পাঠযোগ্যতার জন্য বিবৃতিগুলির পুনঃব্যবহারের সাথে সমস্তকে একত্রে রেখে, 2-যুক্তির উদাহরণের পুরো উত্সটি এখানে:

#include <stdio.h>

void realCreate(int x, int y)
{
  printf("(%d, %d)\n", x, y);
}

#define CREATE_2(x, y) realCreate(x, y)
#define CREATE_1(x) CREATE_2(x, 0)
#define CREATE_0() CREATE_1(0)

#define FUNC_CHOOSER(_f1, _f2, _f3, ...) _f3
#define FUNC_RECOMPOSER(argsWithParentheses) FUNC_CHOOSER argsWithParentheses
#define CHOOSE_FROM_ARG_COUNT(...) FUNC_RECOMPOSER((__VA_ARGS__, CREATE_2, CREATE_1, ))
#define NO_ARG_EXPANDER() ,,CREATE_0
#define MACRO_CHOOSER(...) CHOOSE_FROM_ARG_COUNT(NO_ARG_EXPANDER __VA_ARGS__ ())
#define create(...) MACRO_CHOOSER(__VA_ARGS__)(__VA_ARGS__)

int main()
{
  create();
  create(10);
  create(20, 20);
  //create(30, 30, 30);  // Compilation error
  return 0;
}

যদিও জটিল, কুৎসিত, এপিআই বিকাশকারীকে বোঝা করা হচ্ছে, আমাদের পাগল লোকদের কাছে সি / সি ++ ফাংশনগুলির ওভারলোডিং এবং settingচ্ছিক পরামিতিগুলি সেট করার জন্য একটি সমাধান আসে। আগত ওভারলোড হওয়া এপিআইগুলির ব্যবহার খুব উপভোগ্য এবং মনোরম হয়ে ওঠে। =)

যদি এই পদ্ধতির আরও সম্ভাব্য সরলীকরণ হয় তবে দয়া করে আমাকে জানান

https://github.com/jason-deng/C99FunctionOverload

আবার উজ্জ্বল সকলকেই বিশেষ ধন্যবাদ যা আমাকে এই টুকরোটি কাজের জন্য অনুপ্রাণিত করেছে এবং পরিচালিত করেছে! =)


3
কীভাবে এটি 3 বা 4 ফাংশনে প্রসারিত হয়?
ফিলিইদা

@ ফিলিইডা আদর্শে / জেডি0 এইচএম 5 - শূন্য থেকে পাঁচটি যুক্তি সমর্থনযোগ্য।
xx

9

যার জন্য ভিজ্যুয়াল সি ++ এর সাথে কাজ করে এমন কিছু ভিএ_এনআরজিএস সমাধান বেদনাদায়কভাবে অনুসন্ধান করছে searching নিম্নলিখিত ম্যাক্রো ভিজ্যুয়াল সি ++ এক্সপ্রেস 2010 এ ত্রুটিহীনভাবে (শূন্য প্যারামিটারগুলির সাথেও!) আমার জন্য কাজ করেছে:

#define VA_NUM_ARGS_IMPL(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,N,...) N
#define VA_NUM_ARGS_IMPL_(tuple) VA_NUM_ARGS_IMPL tuple
#define VA_NARGS(...)  bool(#__VA_ARGS__) ? (VA_NUM_ARGS_IMPL_((__VA_ARGS__, 24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1))) : 0

আপনি যদি alচ্ছিক পরামিতি সহ ম্যাক্রো চান তবে আপনি এটি করতে পারেন:

//macro selection(vc++)
#define SELMACRO_IMPL(_1,_2,_3, N,...) N
#define SELMACRO_IMPL_(tuple) SELMACRO_IMPL tuple
#define mymacro1(var1) var1
#define mymacro2(var1,var2) var2*var1
#define mymacro3(var1,var2,var3) var1*var2*var3
#define mymacro(...) SELMACRO_IMPL_((__VA_ARGS__, mymacro3(__VA_ARGS__), mymacro2(__VA_ARGS__), mymacro1(__VA_ARGS__))) 

এটি আমার পক্ষে উপাচার্যের পাশাপাশি কাজ করেছিল। তবে এটি শূন্য পরামিতিগুলির জন্য কাজ করে না।

int x=99;
x=mymacro(2);//2
x=mymacro(2,2);//4
x=mymacro(2,2,2);//8

আমি পাচ্ছিunresolved external symbol _bool referenced in function _main
আভিডান বরিসভ

হ্যাঁ এটি কিছু ক্ষেত্রে ঘটতে পারে। আপনার এই সচেতন হওয়া দরকার যে (#__ ভিএআরজিএস__)? অন্যান্য ম্যাক্রোগুলির চেয়ে আলাদা কারণ এটি রান সময়ে মূল্যায়ন করা হয় run আপনার কেসের উপর নির্ভর করে আপনি কোডের সেই অংশটি বাদ দিতে পারেন।
সিফোরলেট

2
আমি আসলে পেস্টবিন.com/ এইচ 3 টি 75 ডিসিএন দিয়ে শেষ করেছি যা পুরোপুরি কার্যকর হয় (0 টি যুক্তিও)।
আভিদান বোরিসভ

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

এটি ব্যর্থ হয় যেখানে আপনি কিছু উদাহরণ দিতে পারেন?
আভিদান বোরিসভ

7

gcc/ ভারারাগ্স ম্যাক্রোগুলিকেg++ সমর্থন করে তবে আমি এটি মানক বলে মনে করি না, সুতরাং এটি আপনার নিজের ঝুঁকিতে ব্যবহার করুন।


4
এগুলি সি 99 এ স্ট্যান্ডার্ড এবং সেগুলিও সি ++ 0x এ যুক্ত হচ্ছে।
গ্রেফ্যাড

5
#include <stdio.h>

#define PP_NARG(...) \
    PP_NARG_(__VA_ARGS__,PP_RSEQ_N())
#define PP_NARG_(...) \
    PP_ARG_N(__VA_ARGS__)
#define PP_ARG_N( \
    _1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \ 
    _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \
    _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \
    _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \
    _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \
    _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \
    _61,_62,_63,N,...) N
#define PP_RSEQ_N() \
    63,62,61,60,                   \
    59,58,57,56,55,54,53,52,51,50, \
    49,48,47,46,45,44,43,42,41,40, \
    39,38,37,36,35,34,33,32,31,30, \
    29,28,27,26,25,24,23,22,21,20, \
    19,18,17,16,15,14,13,12,11,10, \
    9,8,7,6,5,4,3,2,1,0

#define PP_CONCAT(a,b) PP_CONCAT_(a,b)
#define PP_CONCAT_(a,b) a ## b

#define THINK(...) PP_CONCAT(THINK_, PP_NARG(__VA_ARGS__))(__VA_ARGS__)
#define THINK_0() THINK_1("sector zz9 plural z alpha")
#define THINK_1(location) THINK_2(location, 42)
#define THINK_2(location,answer) THINK_3(location, answer, "deep thought")
#define THINK_3(location,answer,computer) \
  printf ("The answer is %d. This was calculated by %s, and a computer to figure out what this"
          " actually means will be build in %s\n", (answer), (computer), (location))

int
main (int argc, char *argv[])
{
  THINK (); /* On compilers other than GCC you have to call with least one non-default argument */
}

অস্বীকৃতি: বেশিরভাগ ক্ষেত্রে নিরীহ


আপনার কোডে একটি ত্রুটি আছে। দয়া করে করুন :%s/MY_MACRO_/THINK_/g:)
জোও পোর্তেলা

এছাড়াও, এটি জি ++ ব্যবহার করে শূন্য আর্গুমেন্ট নিয়ে কাজ করে নিi686-apple-darwin10-g++-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5664)
জোও পোর্তেলা

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

3

এটি প্রিপ্রোসেসরটির জন্য ডিজাইন করা আসলেই নয়।

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


3
#define MY_MACRO_3(X,Y,Z) ...
#define MY_MACRO_2(X,Y) MY_MACRO(X,Y,5)
#define MY_MACRO_1(X) MY_MACRO(X,42,5)

আপনি কল করতে পারেন যে আপনি কয়টি আরগ পাস করতে যাচ্ছেন তাই ওভারলোডিংয়ের সত্যিই দরকার নেই।


2
আমি আসলে বৈশিষ্ট্যের অস্তিত্ব সম্পর্কে জিজ্ঞাসা করছিলাম।
সেনোক

3

ডেরেক লেডবেটারের কোডের আরও সংক্ষিপ্ত সংস্করণ:

enum
{
    plain = 0,
    bold = 1,
    italic = 2
};


void PrintString(const char* message = NULL, int size = 0, int style = 0)
{
}


#define PRINT_STRING(...) PrintString(__VA_ARGS__)


int main(int argc, char * const argv[])
{ 
    PRINT_STRING("Hello, World!");
    PRINT_STRING("Hello, World!", 18);
    PRINT_STRING("Hello, World!", 18, bold);

    return 0;
}

3

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

তাই আমি এই বৈশিষ্ট্যগুলি সহ একটি সংস্করণ তৈরি করেছি:

  • 0 যুক্তি মামলা কাজ করে
  • অগোছালো অংশে কোনও পরিবর্তন ছাড়াই 1 থেকে 16 টি আর্গুমেন্ট
  • আরও ম্যাক্রো ফাংশন লিখতে সহজ
  • জিসিসি 10, ক্ল্যাং 9, ভিজ্যুয়াল স্টুডিও 2017 এ পরীক্ষিত

বর্তমানে আমি সর্বাধিক ১ argument টি আর্গুমেন্ট তৈরি করেছি, তবে যদি আপনার আরও প্রয়োজন হয় (সত্যিই এখন? আপনি কেবল নির্বোধ হয়ে যাচ্ছেন ...) আপনি FUNC_CHOOSER এবং CHOOSE_FROM_ARG_COUNT টি সম্পাদনা করতে পারেন, তারপরে NO_ARG_EXPANDER এ কিছু কমা যুক্ত করতে পারেন।

বাস্তবায়নের বিষয়ে আরও তথ্যের জন্য দয়া করে জেসন দেং-এর দুর্দান্ত উত্তরটি দেখুন তবে আমি কোডটি এখানে এখানে রেখে দেব:

#include <stdio.h>

void realCreate(int x, int y)
{
    printf("(%d, %d)\n", x, y);
}

// This part you put in some library header:
#define FUNC_CHOOSER(_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15, _f16, ...) _f16
#define FUNC_RECOMPOSER(argsWithParentheses) FUNC_CHOOSER argsWithParentheses
#define CHOOSE_FROM_ARG_COUNT(F, ...) FUNC_RECOMPOSER((__VA_ARGS__, \
            F##_16, F##_15, F##_14, F##_13, F##_12, F##_11, F##_10, F##_9, F##_8,\
            F##_7, F##_6, F##_5, F##_4, F##_3, F##_2, F##_1, ))
#define NO_ARG_EXPANDER(FUNC) ,,,,,,,,,,,,,,,,FUNC ## _0
#define MACRO_CHOOSER(FUNC, ...) CHOOSE_FROM_ARG_COUNT(FUNC, NO_ARG_EXPANDER __VA_ARGS__ (FUNC))
#define MULTI_MACRO(FUNC, ...) MACRO_CHOOSER(FUNC, __VA_ARGS__)(__VA_ARGS__)

// When you need to make a macro with default arguments, use this:
#define create(...) MULTI_MACRO(CREATE, __VA_ARGS__)
#define CREATE_0() CREATE_1(0)
#define CREATE_1(x) CREATE_2(x, 0)
#define CREATE_2(x, y) \
    do { \
        /* put whatever code you want in the last macro */ \
        realCreate(x, y); \
    } while(0)


int main()
{
    create();
    create(10);
    create(20, 20);
    //create(30, 30, 30);  // Compilation error
    return 0;
}

2

আপনি BOOST_PP_OVERLOADএকটি boostলাইব্রেরি থেকে ব্যবহার করতে পারেন ।

অফিসিয়াল বুস্ট ডক এর উদাহরণ :

#include <boost/preprocessor/facilities/overload.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/facilities/empty.hpp>
#include <boost/preprocessor/arithmetic/add.hpp>

#define MACRO_1(number) MACRO_2(number,10)
#define MACRO_2(number1,number2) BOOST_PP_ADD(number1,number2)

#if !BOOST_PP_VARIADICS_MSVC

#define MACRO_ADD_NUMBERS(...) BOOST_PP_OVERLOAD(MACRO_,__VA_ARGS__)(__VA_ARGS__)

#else

// or for Visual C++

#define MACRO_ADD_NUMBERS(...) \
  BOOST_PP_CAT(BOOST_PP_OVERLOAD(MACRO_,__VA_ARGS__)(__VA_ARGS__),BOOST_PP_EMPTY())

#endif

MACRO_ADD_NUMBERS(5) // output is 15
MACRO_ADD_NUMBERS(3,6) // output is 9

0

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


-1

ম্যাক্রোসের সাথে যুক্তি গণনা করার জন্য উপরের উদাহরণগুলির মধ্যে (ডেরেক লেডবেটার, ডেভিড সারকোভস্কি এবং জো ডি থেকে) মাইক্রোসফ্ট ভিসিসি 10 ব্যবহার করে আমার পক্ষে কাজ __VA_ARGS__করেছিল।## বা না হোক), তাই যুক্তি স্থানান্তর যে ক্ষেত্রে উদাহরণগুলি নির্ভর করে কাজ করে না।

সুতরাং, সংক্ষিপ্ত উত্তর, যেমন উপরের আরও অনেকে বলেছেন: না, আপনি ম্যাক্রোগুলি ওভারলোড করতে পারবেন না বা তাদের উপর optionচ্ছিক যুক্তি ব্যবহার করতে পারবেন না।


1
আপনি পারেন, তবে কেবল সি 99 বা সি ++ 11 এ (__VA_ARGS__ থাকার কারণে)। ভিসি 2010 হ'ল সি 89 / সি ++ 03 (সি ++ 11 এর কিছু বিটগুলি শুরু হয়েছে, তবে এখনও তা নয়)।
পিত্তজক
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.