C ++ এ আর্গুমেন্টের পরিবর্তনশীল সংখ্যা?


293

আমি কীভাবে এমন একটি ফাংশন লিখতে পারি যা একটি পরিবর্তনশীল সংখ্যক আর্গুমেন্ট গ্রহণ করে? এটা কি সম্ভব?


49
এই সময়ে সি ++ এর সাথে এই প্রশ্নের উত্তরগুলি অনেক বেশি পৃথক হবে
K-ballo

1
@ কে-ballo আমি সি ++ 11 উদাহরণ হিসেবে যোগ যেহেতু একটি সাম্প্রতিক প্রশ্ন একই জিনিস সম্প্রতি জিজ্ঞাসা এবং আমি যাতে এটা বন্ধ ন্যায্যতা করার জন্য এই প্রয়োজনীয় এক অনুভূত stackoverflow.com/questions/16337459/...
শফিক Yaghmour

1
আমার উত্তরে প্রাক সি ++ ১১ টি বিকল্প যুক্ত করা হয়েছে, সুতরাং এটি এখন বেশিরভাগ পছন্দগুলি উপলভ্য করে।
শফিক ইয়াহমুর

@ কে-বেলো সি -+ তে এটি করার কোনও উপায় নেই যদি আপনার জোর করে যুক্তি প্রকারের প্রয়োজন হয় .. foo (int ... মান) এর মতো কোনও নির্মাণ নয়: / আপনি যদি প্রকারের বিষয়ে চিন্তা করেন না, তবে হ্যাঁ, ভিন্ন ভিন্ন টেম্পলেট সি ++ এ 11 দুর্দান্ত কাজ করে
গ্রেওয়াল্ফ

উত্তর:


152

আপনার সম্ভবত করা উচিত নয় এবং আপনি সম্ভবত যা করতে চান তা নিরাপদ এবং সহজ উপায়ে করতে পারেন। প্রযুক্তিগতভাবে আপনি stdarg.h অন্তর্ভুক্ত সি মধ্যে পরিবর্তনশীল সংখ্যক আর্গুমেন্ট ব্যবহার করতে। থেকে আপনি পাবেন va_listটাইপ সেইসাথে তিনটি কার্যকারিতা যে কাজ তে এটি বলা va_start(), va_arg()এবং va_end()

#include<stdarg.h>

int maxof(int n_args, ...)
{
    va_list ap;
    va_start(ap, n_args);
    int max = va_arg(ap, int);
    for(int i = 2; i <= n_args; i++) {
        int a = va_arg(ap, int);
        if(a > max) max = a;
    }
    va_end(ap);
    return max;
}

আপনি যদি আমাকে জিজ্ঞাসা করেন, এটি একটি গোলযোগ। এটি দেখতে খারাপ লাগছে, এটি অনিরাপদ এবং এটি প্রযুক্তিগত বিবরণ দিয়ে পূর্ণ যা আপনি ধারণাগতভাবে অর্জন করার চেষ্টা করছেন তার সাথে কিছুই করার নেই। পরিবর্তে, ওভারলোডিং বা উত্তরাধিকার / পলিমারফিজম, বিল্ডার প্যাটার্ন (যেমন operator<<()স্ট্রিমগুলির মধ্যে) বা ডিফল্ট আর্গুমেন্ট ইত্যাদি ব্যবহারের বিষয়ে বিবেচনা করুন all এগুলি আরও সুরক্ষিত: সংকলকটি আপনি কী করার চেষ্টা করছেন সে সম্পর্কে আরও জানতে পারবেন যাতে আরও কিছু ঘটনা বন্ধ হতে পারে more তুমি তোমার পা উড়িয়ে দেওয়ার আগে


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

3
...সিনট্যাক্সের আগে কমপক্ষে একটি যুক্তি সরবরাহ করা কি প্রয়োজনীয় ?
লেজার

3
@ লেজার এটি কোনও ভাষা বা গ্রন্থাগারের প্রয়োজনীয়তা নয়, তবে মানক গ্রন্থাগারটি আপনাকে তালিকাটির দৈর্ঘ্য বলার অর্থ দেয় না। আপনাকে এই তথ্য দেওয়ার জন্য কলারের দরকার আছে অন্যথায় এটি নিজেকে নির্ধারণ করুন। ক্ষেত্রে printf(), উদাহরণস্বরূপ, ফাংশন কত অতিরিক্ত আর্গুমেন্ট এটা পরিবর্তনশীল যুক্তি তালিকায় আশা করা উচিত জিনিসটা বিশেষ টোকেন জন্য স্ট্রিং যুক্তি parses।
উইলহেমটেল

11
আপনার সম্ভবত <cstdarg>সি ++ এর পরিবর্তে<stdarg.h>
নতুনচ্যাক

11
পরিবর্তনশীল সংখ্যক আর্গুমেন্টগুলি ডিবাগের জন্য বা ফাংশন / পদ্ধতিগুলির জন্য দুর্দান্ত যা কিছু অ্যারে পূরণ করে। এছাড়াও এটি বেশিরভাগ গাণিতিক ক্রিয়াকলাপের জন্য দুর্দান্ত, যেমন সর্বোচ্চ, মিনিট, যোগফল, গড় ... আপনি যখন এতে গোলমাল করবেন না তখন গোলমাল করবেন না।
টোমা জাটো - মনিকা

395

ইন সি ++ 11 আপনি দুটি নতুন অপশন আছে, Variadic ফাংশন রেফারেন্স পৃষ্ঠা বিকল্প ধারা বলে:

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

নীচে উভয় বিকল্প দেখানোর একটি উদাহরণ দেওয়া হয়েছে ( এটি সরাসরি দেখুন ):

#include <iostream>
#include <string>
#include <initializer_list>

template <typename T>
void func(T t) 
{
    std::cout << t << std::endl ;
}

template<typename T, typename... Args>
void func(T t, Args... args) // recursive variadic function
{
    std::cout << t <<std::endl ;

    func(args...) ;
}

template <class T>
void func2( std::initializer_list<T> list )
{
    for( auto elem : list )
    {
        std::cout << elem << std::endl ;
    }
}

int main()
{
    std::string
        str1( "Hello" ),
        str2( "world" );

    func(1,2.5,'a',str1);

    func2( {10, 20, 30, 40 }) ;
    func2( {str1, str2 } ) ;
} 

আপনি যদি ব্যবহার করছেন gccবা clangআমরা PRETTY_FUNCTION ম্যাজিক ভেরিয়েবলটি ফাংশনের প্রকারের স্বাক্ষর প্রদর্শন করতে পারি যা যা চলছে তা বুঝতে সহায়তা করতে পারে। উদাহরণস্বরূপ:

std::cout << __PRETTY_FUNCTION__ << ": " << t <<std::endl ;

উদাহরণে বৈকল্পিক ফাংশনগুলির জন্য নিম্নলিখিত ফলাফলের ফলাফল হবে ( এটি সরাসরি দেখুন ):

void func(T, Args...) [T = int, Args = <double, char, std::basic_string<char>>]: 1
void func(T, Args...) [T = double, Args = <char, std::basic_string<char>>]: 2.5
void func(T, Args...) [T = char, Args = <std::basic_string<char>>]: a
void func(T) [T = std::basic_string<char>]: Hello

ভিজ্যুয়াল স্টুডিওতে আপনি ফুনসিএসআইজি ব্যবহার করতে পারেন ।

প্রি সি সি ++ 11 আপডেট করুন

প্রাক সি ++ 11 জন্য বিকল্প এসটিডি :: initializer_list হবে এসটিডি :: ভেক্টর বা অন্যান্য এক মান পাত্রে :

#include <iostream>
#include <string>
#include <vector>

template <class T>
void func1( std::vector<T> vec )
{
    for( typename std::vector<T>::iterator iter = vec.begin();  iter != vec.end(); ++iter )
    {
        std::cout << *iter << std::endl ;
    }
}

int main()
{
    int arr1[] = {10, 20, 30, 40} ;
    std::string arr2[] = { "hello", "world" } ; 
    std::vector<int> v1( arr1, arr1+4 ) ;
    std::vector<std::string> v2( arr2, arr2+2 ) ;

    func1( v1 ) ;
    func1( v2 ) ;
}

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

#include <iostream>
#include <string>
#include <cstdarg>

void simple_printf(const char *fmt, ...)
{
    va_list args;
    va_start(args, fmt);

    while (*fmt != '\0') {
        if (*fmt == 'd') {
            int i = va_arg(args, int);
            std::cout << i << '\n';
        } else if (*fmt == 's') {
            char * s = va_arg(args, char*);
            std::cout << s << '\n';
        }
        ++fmt;
    }

    va_end(args);
}


int main()
{
    std::string
        str1( "Hello" ),
        str2( "world" );

    simple_printf("dddd", 10, 20, 30, 40 );
    simple_printf("ss", str1.c_str(), str2.c_str() ); 

    return 0 ;
} 

ব্যবহার variadic ফাংশন এছাড়াও আর্গুমেন্ট আপনি পাস করতে পারেন, যা বিস্তারিত হয় বিধিনিষেধ দিয়ে আসে খসড়া C ++ স্ট্যান্ডার্ডের অধ্যায় 5.2.2 ফাংশন কল অনুচ্ছেদ 7 :

যখন কোনও প্রদত্ত আর্গুমেন্টের জন্য কোনও প্যারামিটার না থাকে তখন আর্গুমেন্টটি এমনভাবে পাস করা হয় যাতে প্রাপ্ত ফাংশনটি ভায়ার্গ (18.7) দিয়ে আর্গুমেন্টের মান অর্জন করতে পারে। লভ্যু-টু-রেভ্যালু (৪.১), অ্যারে-টু-পয়েন্টার (৪.২) এবং ফাংশন-টু-পয়েন্টার (৪.৩) স্ট্যান্ডার্ড রূপান্তরগুলি আর্গুমেন্টের অভিব্যক্তিতে সঞ্চালিত হয়। এই রূপান্তরগুলির পরে, যদি যুক্তিতে গাণিতিক, গণনা, পয়েন্টার, পয়েন্টার অফ মেম্বার বা শ্রেণীর ধরণ না থাকে তবে প্রোগ্রামটি দুর্গঠিত। যদি আর্গুমেন্টটির কোনও POD বিবিধ শ্রেণি থাকে (ধারা 9), আচরণটি অপরিজ্ঞাত। [...]


আপনার typenameবনাম classব্যবহার উপরে উদ্দেশ্যমূলক? যদি তা হয় তবে দয়া করে ব্যাখ্যা করুন।
কেভিনার্পে

1
@ কেভিনার্পে ইচ্ছাকৃত নয়, যদিও এটি কিছু পরিবর্তন করে না।
শফিক ইয়াঘমোর

আপনার প্রথম লিঙ্কটি সম্ভবত তার পরিবর্তে সম্ভবত en.cppreferences.com/w/cpp/language/variadic_arguments হতে হবে।
আলেক্সি রোমানভ

initializer_listপুনরাবৃত্তি গ্রহণ করে কোনও ফাংশন করা কি সম্ভব ?
idclev 463035818

33

একটি সি ++ 17 সমাধান: সম্পূর্ণ টাইপ সুরক্ষা + দুর্দান্ত কলিং সিনট্যাক্স

যেহেতু সি ++ 11 এ ভেরিয়ডিক টেম্পলেটগুলির প্রবর্তন এবং সি ++ 17 এ ফোল্ডার এক্সপ্রেশনগুলি সংযুক্ত করা সম্ভব, তাই কলকারী সাইটে কল করা যায় এমন একটি টেমপ্লেট-ফাংশনটি সংজ্ঞায়িত করা সম্ভব যে এটি কোনও বৈকল্পিক ফাংশন ছিল তবে তার সুবিধার সাথে :

  • দৃ strongly়ভাবে নিরাপদ টাইপ করা;
  • আর্গুমেন্টের সংখ্যা সম্পর্কিত রান-টাইম তথ্য বা "স্টপ" যুক্তি ব্যবহার না করে কাজ করুন।

মিশ্র যুক্তি প্রকারের জন্য এখানে একটি উদাহরণ is

template<class... Args>
void print(Args... args)
{
    (std::cout << ... << args) << "\n";
}
print(1, ':', " Hello", ',', " ", "World!");

এবং আরও কার্যকরভাবে যুক্তিযুক্ত সমস্ত যুক্তির সাথে মেলে:

#include <type_traits> // enable_if, conjuction

template<class Head, class... Tail>
using are_same = std::conjunction<std::is_same<Head, Tail>...>;

template<class Head, class... Tail, class = std::enable_if_t<are_same<Head, Tail...>::value, void>>
void print_same_type(Head head, Tail... tail)
{
    std::cout << head;
    (std::cout << ... << tail) << "\n";
}
print_same_type("2: ", "Hello, ", "World!");   // OK
print_same_type(3, ": ", "Hello, ", "World!"); // no matching function for call to 'print_same_type(int, const char [3], const char [8], const char [7])'
                                               // print_same_type(3, ": ", "Hello, ", "World!");
                                                                                              ^

অধিক তথ্য:

  1. ভেরিয়াদিক টেম্পলেটগুলি, প্যারামিটার প্যাক প্যারামিটার প্যাক হিসাবেও পরিচিত (সি ++ 11) - cppreferences.com
  2. ভাঁজ এক্সপ্রেশন ভাঁজ এক্সপ্রেশন (যেহেতু সি ++ 17) - cppreferences.com
  3. কলিরুতে একটি সম্পূর্ণ প্রোগ্রাম প্রদর্শন দেখুন ।

13
একদিন অসুস্থ আশা করি আমি পড়তে পারিtemplate<class Head, class... Tail, class = std::enable_if_t<are_same<Head, Tail...>::value, void>>
এলাদিয়ান

1
@ এলাদিয়ান এটি পড়েন "এই জিনিসটি কেবল তখনই সক্ষম হয় Headএবং যদি Tail... একই হয় ", যেখানে " একই " মানে হয় std::conjunction<std::is_same<Head, Tail>...>। এই সর্বশেষ Headনির্ধারণটি Tail..." সকলের সমান " হিসাবে পড়ুন ।
YSC

24

সি ++ 11 এ আপনি করতে পারেন:

void foo(const std::list<std::string> & myArguments) {
   //do whatever you want, with all the convenience of lists
}

foo({"arg1","arg2"});

এফটিডব্লিউ তালিকা!


19

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

ব্যক্তিগতভাবে, আমি এটিকে এত মার্জিত বিবেচনা করি যে সি ++ এর মধ্যে একটি পরিবর্তনশীল যুক্তি ফাংশন নিয়েও আমি বিরক্ত করব না যতক্ষণ না এই সংকলকটির সি ++ 11 ভেরিয়েবল আর্গুমেন্ট টেম্পলেটগুলির সমর্থন না থাকে।


কম শব্দার্থক, ভিজ্যুয়াল শব্দের সাথে এটি করার কোনও উপায় আছে কি?
ক্রিস্টোফার

@ ডনলান - আপনি যদি সি ++ 17 ব্যবহার করছেন তবে কিছু ক্ষেত্রে জিনিসগুলিকে অনেক সহজ করে তুলতে আপনি ভাঁজ প্রকাশ করতে পারেন (সৃজনশীলভাবে এখানে ভাবেন, ,ভাঁজ প্রকাশের সাথে অপারেটরটি ব্যবহার করতে পারেন )। অন্যথায়, আমি এটি মনে করি না।
সর্বজনীন

15

সি স্টাইলের ভেরিয়াদিক ফাংশন সি ++ এ সমর্থিত।

তবে বেশিরভাগ সি ++ লাইব্রেরি বিকল্প আইডিয়াম ব্যবহার করে যেমন 'c' printfফাংশনটি ভেরিয়েবল আর্গুমেন্ট গ্রহণ করে যা c++ coutবস্তু <<ওভারলোডিং ব্যবহার করে যা প্রকারের সুরক্ষা এবং এডিটিগুলিকে সম্বোধন করে (সম্ভবত বাস্তবায়নের সরলতার জন্য ব্যয় করে)।


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

13

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

template <typename T> void f(std::vector<T> const&);
std::vector<int> my_args;
my_args.push_back(1);
my_args.push_back(2);
f(my_args);

এইভাবে আপনি প্রকারের সুরক্ষা পাবেন এবং এই বৈকল্পিক যুক্তিগুলির যৌক্তিক অর্থ স্পষ্ট হবে।

অবশ্যই এই পদ্ধতির পারফরম্যান্স সংক্রান্ত সমস্যা থাকতে পারে তবে আপনি মূল্য পরিশোধ করতে পারবেন না তা নিশ্চিত হওয়া পর্যন্ত আপনি সেগুলি নিয়ে চিন্তা করবেন না। এটি সি ++ এর এক ধরণের "পাইথোনিক" পদ্ধতির ...


6
ক্লিনারটি ভেক্টরগুলি প্রয়োগ না করা হবে। পরিবর্তে এসটিএল-স্টাইলযুক্ত সংগ্রহ নির্দিষ্ট করে একটি টেম্পলেট যুক্তি ব্যবহার করুন তারপরে যুক্তির শুরু এবং শেষ পদ্ধতিগুলি ব্যবহার করে এর মাধ্যমে পুনরাবৃত্তি করুন। আপনি std :: ভেক্টর <টি>, সি ++ 11 এর এসটিডি :: অ্যারে <টি, এন>, স্টাডি :: ইনিশিয়াল_লিস্ট <T> ব্যবহার করতে পারেন বা এমনকি আপনার নিজের সংগ্রহ তৈরি করতে পারেন।
জেনস bkerblom

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

8

একমাত্র উপায় হ'ল এখানে বর্ণিত হিসাবে সি স্টাইলের ভেরিয়েবল আর্গুমেন্ট ব্যবহার । মনে রাখবেন যে এটি কোনও প্রস্তাবিত অনুশীলন নয়, কারণ এটি টাইপসেফ এবং ত্রুটি-প্রবণ নয়।


ত্রুটিযুক্ত প্রবণ দ্বারা আমি ধরে নিচ্ছি আপনি সম্ভবত খুব বিপজ্জনক মানে? বিশেষত যখন অবিশ্বস্ত ইনপুট নিয়ে কাজ করা হয়।
কেভিন লনি

হ্যাঁ, তবে ধরণের সুরক্ষা সমস্যার কারণে। নিয়মিত প্রিন্টফের যে সমস্ত সম্ভাব্য সমস্যা রয়েছে সেগুলি ভেবে দেখুন: বিন্যাসের স্ট্রিংগুলি পাস হওয়া যুক্তিগুলির সাথে মেলে না and প্রিন্টফ একই কৌশল ব্যবহার করে, বিটিডাব্লু।
ডেভ ভ্যান ডেন এয়েণ্ডে

7

সি-স্টাইলের ভারার্গস ( ...) অবলম্বন না করে এটি করার কোনও মানক সি ++ উপায় নেই ।

অবশ্যই ডিফল্ট আর্গুমেন্ট রয়েছে যা প্রসঙ্গে নির্ভর করে তাত্ক্ষণিক সংখ্যার মতো "চেহারা" সাজায়:

void myfunc( int i = 0, int j = 1, int k = 2 );

// other code...

myfunc();
myfunc( 2 );
myfunc( 2, 1 );
myfunc( 2, 1, 0 );

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


4

এটি সম্ভব যে আপনি ওভারলোডিং বা ডিফল্ট পরামিতিগুলি চান - ডিফল্ট পরামিতিগুলির সাথে একই ফাংশনটি সংজ্ঞায়িত করুন:

void doStuff( int a, double termstator = 1.0, bool useFlag = true )
{
   // stuff
}

void doStuff( double std_termstator )
{
   // assume the user always wants '1' for the a param
   return doStuff( 1, std_termstator );
}

এটি আপনাকে চারটি আলাদা আলাদা কলের মাধ্যমে পদ্ধতিটিতে কল করতে দেয়:

doStuff( 1 );
doStuff( 2, 2.5 );
doStuff( 1, 1.0, false );
doStuff( 6.72 );

... অথবা আপনি সি এর থেকে v_args আহ্বানের সম্মেলন সন্ধান করতে পারেন


2

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

f(int a)
    {int res=a; return res;}
f(int a, int b)
    {int res=a+b; return res;}

এবং তাই ...


2

বৈচিত্র্যমূলক টেম্পলেটগুলি ব্যবহার করে উদাহরণস্বরূপ console.logজাভাস্ক্রিপ্টে দেখা গেছে পুনরুত্পাদন :

Console console;
console.log("bunch", "of", "arguments");
console.warn("or some numbers:", 1, 2, 3);
console.error("just a prank", "bro");

ফাইলের নাম যেমন js_console.h:

#include <iostream>
#include <utility>

class Console {
protected:
    template <typename T>
    void log_argument(T t) {
        std::cout << t << " ";
    }
public:
    template <typename... Args>
    void log(Args&&... args) {
        int dummy[] = { 0, ((void) log_argument(std::forward<Args>(args)),0)... };
        cout << endl;
    }

    template <typename... Args>
    void warn(Args&&... args) {
        cout << "WARNING: ";
        int dummy[] = { 0, ((void) log_argument(std::forward<Args>(args)),0)... };
        cout << endl;
    }

    template <typename... Args>
    void error(Args&&... args) {
        cout << "ERROR: ";
        int dummy[] = { 0, ((void) log_argument(std::forward<Args>(args)),0)... };
        cout << endl;
    }
};

1

অন্যরা যেমন বলেছে, সি-স্টাইলের ভ্যারাগস। তবে আপনি ডিফল্ট যুক্তিগুলির সাথেও অনুরূপ কিছু করতে পারেন।


আপনি বিস্তারিত বলতে পারেন?
মনিকার মামলার তহবিল

@ কিপেইট্যাক্সস: ডিফল্ট যুক্তি দিয়ে এটি কীভাবে করা যায় তার উদাহরণের জন্য, জোল্টনের উত্তরটি দেখুন।
থমাস প্যাড্রন-ম্যাকার্থি

0

এটি এখনই সম্ভব ... বুস্ট যেকোন এবং টেম্পলেট ব্যবহার করে এই ক্ষেত্রে, আর্গুমেন্টের প্রকারটি মিশ্রিত করা যেতে পারে

#include <boost/any.hpp>
#include <iostream>

#include <vector>
using boost::any_cast;

template <typename T, typename... Types> 
void Alert(T var1,Types... var2) 
{ 

    std::vector<boost::any> a(  {var1,var2...});

    for (int i = 0; i < a.size();i++)
    {

    if (a[i].type() == typeid(int))
    {
        std::cout << "int "  << boost::any_cast<int> (a[i]) << std::endl;
    }
    if (a[i].type() == typeid(double))
    {
        std::cout << "double "  << boost::any_cast<double> (a[i]) << std::endl;
    }
    if (a[i].type() == typeid(const char*))
    {
        std::cout << "char* " << boost::any_cast<const char*> (a[i]) <<std::endl;
    }
    // etc
    }

} 


void main()
{
    Alert("something",0,0,0.3);
}

0

শব্দার্থগতভাবে সহজতম, পারফরম্যান্ট এবং সর্বাধিক গতিশীল বিকল্পের জন্য সি এবং সি ++ সমাধানগুলি একত্রিত করুন। যদি আপনি ভুল করে থাকেন তবে অন্য কিছু চেষ্টা করুন।

// spawn: allocate and initialize (a simple function)
template<typename T>
T * spawn(size_t n, ...){
  T * arr = new T[n];
  va_list ap;
  va_start(ap, n);
  for (size_t i = 0; i < n; i++)
    T[i] = va_arg(ap,T);
  return arr;
}

ব্যবহারকারী লিখেছেন:

auto arr = spawn<float> (3, 0.1,0.2,0.3);

শব্দার্থকভাবে, এটি দেখতে একটি এন-আর্গুমেন্ট ফাংশনের মতো দেখতে এবং অনুভব করা। হুডের নীচে, আপনি এটিকে কোনও উপায়ে বা অন্য কোনও উপায়ে আনতে পারবেন।


-1

সমস্ত আর্গুমেন্ট কনস্ট এবং একই ধরণের থাকলে আমরা একটি ইনিশিয়ালার_লিস্টও ব্যবহার করতে পারি


-2
int fun(int n_args, ...) {
   int *p = &n_args; 
   int s = sizeof(int);
   p += s + s - 1;
   for(int i = 0; i < n_args; i++) {
     printf("A1 %d!\n", *p);
     p += 2;
   }
}

সরল সংস্করণ


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