আমি কীভাবে সি ++ এ কোনও ফাংশন নামের একটি উপনাম নিযুক্ত করব?


101

কোনও প্রকার, পরিবর্তনশীল বা একটি নেমস্পেসের জন্য একটি নতুন নাম তৈরি করা সহজ। তবে আমি কীভাবে কোনও ফাংশনে একটি নতুন নাম নির্ধারণ করব? উদাহরণস্বরূপ, আমি নাম ব্যবহার করতে চাই hollerজন্য printf। # নির্ধারণটি সুস্পষ্ট ... অন্য কোনও উপায়ে?

সমাধান:

  1. #define holler printf
  2. void (*p)() = fn; //function pointer
  3. void (&r)() = fn; //function reference
  4. inline void g(){ f(); }

সব কিছুর জন্য তোমাকে ধন্নবাদ. আমার সহকর্মীরা করত প্রেম এটা দেখতে পান void (&NewName)(some_vector&, float, float, float, float) = OldName;যে আমার পরবর্তী পরীক্ষা করুন।
Agnel Kurian

19
আপনি স্ট্যান্ডার্ড লাইব্রেরি ফাংশনের জন্য এলোমেলো নাম ব্যবহার করতে দেখে তারা যতটা ভালোবাসে না তত বেশি নয়।
জাল্ফ

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

4
নিল, নিখুঁতভাবে T &a = b;এর জন্য একটি নতুন নাম তৈরি করে btypedefপ্রকারের জন্য এবং namespace A=B;নেমস্পেসের জন্য।
অগ্নেল কুরিয়ান

4
আছে using BaseClass::BaseClassMethod, আছে using AliasType = Type;এবং আছে namespace AliasNamespace = Namespace;। আমরা কী অনুপস্থিত তা হ'লusing AliasFunction = Function;
anton_rh

উত্তর:


114

বিভিন্ন পদ্ধতি আছে:

  • নন-টেম্পলেট অ-ওভারলোড হওয়া ফাংশন সহ সি ++ 11 এর মাধ্যমে আপনি কেবল ব্যবহার করতে পারেন:

    const auto& new_fn_name = old_fn_name;
    
  • যদি এই ফাংশনে একাধিক ওভারলোড থাকে তবে আপনার ব্যবহার করা উচিত static_cast:

    const auto& new_fn_name = static_cast<OVERLOADED_FN_TYPE>(old_fn_name);
    

    উদাহরণ: ফাংশন দুটি ওভারলোড আছে std::stoi

    int stoi (const string&, size_t*, int);
    int stoi (const wstring&, size_t*, int);
    

    আপনি যদি প্রথম সংস্করণে একটি উপাধি তৈরি করতে চান তবে আপনার নিম্নলিখিতটি ব্যবহার করা উচিত:

    const auto& new_fn_name = static_cast<int(*)(const string&, size_t*, int)>(std::stoi);
    

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

  • সি ++ 14 দিয়ে আপনি constexprটেমপ্লেট ভেরিয়েবলগুলির সাথে আরও এগিয়ে যেতে পারেন । এটি আপনাকে টেম্প্লেটড ক্রিয়াকলাপগুলি করতে দেয়:

    template<typename T>
    constexpr void old_function(/* args */);
    
    template<typename T>
    constexpr auto alias_to_old = old_function<T>;
    
  • অধিকন্তু, সি ++ 11 দিয়ে শুরু করে আপনার একটি ফাংশন বলা হয় std::mem_fnযা সদস্যের সদস্যদের ফাংশন দেয়। নিম্নলিখিত উদাহরণটি দেখুন:

    struct A {
       void f(int i) {
          std::cout << "Argument: " << i << '\n';
       }
    };
    
    
    A a;
    
    auto greet = std::mem_fn(&A::f); // alias to member function
    // prints "Argument: 5"
    greet(a, 5); // you should provide an object each time you use this alias
    
    // if you want to bind an object permanently use `std::bind`
    greet_a = std::bind(greet, a, std::placeholders::_1);
    greet_a(3); // equivalent to greet(a, 3) => a.f(3);
    

4
দুর্দান্ত, সি ++ 98 কেমন? আমার কাছে ক্লাস ডাব্লু / 2 "রিসেট" ওভারলোডগুলি সেট এবং রিসেট করতে ব্যবহৃত হয়েছে। অভ্যন্তরীণভাবে, কোনও সমস্যা নেই। বাহ্যিক ব্যবহারকারীর জন্য আমি "সেট" হিসাবে উপনাম রাখতে চেয়েছিলাম সুতরাং এটি প্রসঙ্গের জন্য স্বজ্ঞাত (একটি ডিফল্ট-নির্মিত, সাফ () 'ডি ইত্যাদি সেট করুন; ওয়ার্কিং অবজেক্টটি পুনরায় সেট করুন)। শ্রেণীর পদ্ধতি: (1) "শূন্য (& সেট) (কনস্ট্রিং স্ট্রিং &, কনস্ট বোল, কনস্ট বোল);" (2) অকার্যকর (& সেট) (কনস্ট্রিং স্ট্রিং &, কনস্ট ইন্ট, কনস্ট বুল); 2 "রিসেট" ডাব্লু / সংশ্লিষ্ট স্বাক্ষরগুলি কাজ করে। যেহেতু আমার ক্লাস ঘোষণায় স্বাক্ষর রয়েছে তাই আমি কি কেবল ক্লাস-ইনিশিয়াল করতে পারি: সেট (রিসেট), সেট (রিসেট) করতে পারি। যদি তা না হয় তবে আপনার সুস্পষ্ট স্ট্যাটিক_কাস্ট উদাহরণটি কী কাজ করবে?
Luv2code

8
constexprটেমপ্লেট ভেরিয়েবলের পদ্ধতির সাথে কোনও সমস্যা আছে বলে মনে হচ্ছে : উপন্যাসটি টাইপ ছাড়গুলি করতে পারে না। সংকলকটির জন্য আমাকে টেমপ্লেট প্যারামিটার তালিকা সরবরাহ করতে হবে (আমি একটি বৈকল্পিক টেম্পলেট ফাংশন লিখছি): টেম্পলেট আর্গুমেন্ট তালিকা ছাড়া চলক টেমপ্লেট ʻalias_to_old 'উল্লেখ করতে পারি না
user69818

4
constexpr auto new_fn_name = old_fn_nameসি ++ 11 এ কাজ করে (কমপক্ষে জিসিসি 4.9.2 এ) এবং রাখার চেয়ে ভাল &। এর জন্য কলটি সর্বদা পয়েন্টারের মাধ্যমে করা প্রয়োজন হয় না এবং এভাবে কলটির জায়গায় ফাংশনটি ইনলাইন করা যায়।
ony

সি ++ ১৪ জেনেরিক ল্যাম্বডাসের সাহায্যে আমি নিম্নলিখিতটি করতে সক্ষম হয়েছি যা লক্ষ্য ফাংশনে একাধিক ওভারলোড থাকলে তাও কাজ করা উচিত: constexpr auto holler = [] ( auto &&...args ) { return printf( std::forward<decltype(args)>( args )... ); };
অ্যান্টনি হল

4
ব্যবহার std::mem_fnহয় না উপনাম যেহেতু এটা জ্ঞান পিছনে আরো অনেক কিছু জাদু সম্পাদন করে।
cgsdfc

35

আপনি একটি ফাংশন পয়েন্টার বা একটি ফাংশন রেফারেন্স তৈরি করতে পারেন:

void fn()
{
}

//...

void (*p)() = fn;//function pointer
void (&r)() = fn;//function reference

4
এই কেক লাগে। আমি ফাংশন রেফারেন্স সম্পর্কে জানতাম না।
অগ্নেল কুরিয়ান

@ ভ্যালকান: তারা প্রায় একই রকম যে আপনি উভয়কে একই বাক্য গঠন সহ কল ​​করতে পারেন, তবে তাদের ঠিকানাগুলি একটু আলাদা। কোনও ঠিকানা সম্বলিত নিজস্ব মেমরির স্থান গ্রহণ করে না।
ব্রায়ান আর বন্ডি

4
আপনি কীভাবে ফোন করবেন fn, উপনামটি ব্যবহার করে? আপনি ফাংশন পয়েন্টার এবং ফাংশন রেফারেন্স ব্যাখ্যা করতে পারেন? কিভাবে তারা ব্যতিক্রম? তারা কি এখানে একই?
ma11hew28

4
@ ম্যাট, আপনি এফএনএনকে কল করবেন ঠিক সেভাবেই call r();
অগ্নেল কুরিয়ান

আপনি উদাহরণস্বরূপ পদ্ধতির জন্য এটি কীভাবে করবেন? সম্পাদনা: এটি সংকলিত বলে মনে হচ্ছে:void (&r)() = this->fn;
স্যাম

21
typedef int (*printf_alias)(const char*, ...);
printf_alias holler = std::printf;

আপনি ভাল করতে হবে।


গ্লোবাল নেমস্পেসে প্রিন্টফ নেই?
অগ্নেল কুরিয়ান

4
এটি বিশ্বব্যাপী যদি আপনি <stdio.h> অন্তর্ভুক্ত করেন তবে আপনি যদি <cstdio> অন্তর্ভুক্ত করেন তবে এসটিডি
ইনজেকটিলো

@einpoklum আছে: সঙ্গে কোন কিছুই ভুল না decltype , কিন্তু উত্তর থেকে 2010 পিছনে পরে সেখানে ছিলাম না decltypeযেমন C ++ 11 চালু করা হয়।
তবুও এটি


7

একটি ইনলাইন মোড়ক ব্যবহার করুন। আপনি উভয় এপিআই পান তবে একক বাস্তবায়ন রাখুন।


3

ফ্লুয়েণ্টসিপ থেকে : ALIAS_TEMPLATE_FUNCTION (ফ, জি)

#define ALIAS_TEMPLATE_FUNCTION(highLevelF, lowLevelF) \
template<typename... Args> \
inline auto highLevelF(Args&&... args) -> decltype(lowLevelF(std::forward<Args>(args)...)) \
{ \
    return lowLevelF(std::forward<Args>(args)...); \
}

1

সি ++ ১৪ জেনেরিক ল্যাম্বডাসের সাহায্যে আমি নিম্নলিখিতটি করতে সক্ষম হয়েছি যা লক্ষ্য ফাংশনে একাধিক ওভারলোড থাকলে তাও কাজ করা উচিত:

constexpr auto holler = [] ( auto &&...args ) {
        return printf( std::forward<decltype(args)>( args )... );
    };

হাহ! এটি আমাকে দু: খিত করে তুলেছে এমনকি এমনকী @ ব্যবহারকারী 5534993 যিনি আপনাকে এই উত্তর জমা দেওয়ার জন্য প্রাথমিকভাবে চাপ দিয়েছেন, তারপরে কোনও উপায়ে আপনার পথে যেতে পারেনি। ভাল, এখানে, আমার উপর একটি আছে।

0

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

namespace deep {
  namespace naming {
    namespace convention {
      void myFunction(int a, char b) {}
    }
  }
}
int main(void){
  // A pain to write it all out every time
  deep::naming::convention::myFunction(5, 'c');

  // Using keyword can be done this way
  using deep::naming::convention::myFunction;
  myFunction(5, 'c');  // Same as above
}

আপনি সর্বদা এটি কোনও ফাইলের শীর্ষ স্তরে ব্যবহার করতে পারলেও এটি একটি সুযোগের মধ্যে সীমাবদ্ধ থাকার সুবিধাও রয়েছে। আমি প্রায়শই এটির জন্য ব্যবহার করি coutএবং endlতাই কোনও ফাইলের শীর্ষে ক্লাসিকটি stdসহ আমার সমস্ত কিছু আনার দরকার নেই using namespace std;, তবে আপনি যদি std::this_thread::sleep_for()কোনও ফাইল বা ফাংশনে প্রচুর মতো কিছু ব্যবহার করেন তবে সমস্ত জায়গায় নয়, এবং দরকারী নেমস্পেস থেকে অন্য কোনও ফাংশন নয়। সর্বদা হিসাবে, এটি .h ফাইলগুলিতে এটি ব্যবহার করতে নিরুৎসাহিত করা হয়, বা আপনি বিশ্বব্যাপী নেমস্পেসকে দূষিত করবেন।

এটি উপরের "পুনর্নামকরণ" এর মতো নয়, তবে প্রায়শই এটি সত্যই যা চেয়েছিল।

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