__PRETTY_FUNCTION__, __FUNCTION__, __func__ এর মধ্যে পার্থক্য কী?


221

মধ্যে পার্থক্য কি __PRETTY_FUNCTION__, __FUNCTION__, __func__, এবং যেখানে তারা নথিভুক্ত করা হয়? কোনটি ব্যবহার করব তা আমি কীভাবে সিদ্ধান্ত নেব?

উত্তর:


266

__func__একটি স্পষ্টভাবে ঘোষিত শনাক্তকারী যা কোনও ফাংশনের অভ্যন্তরে যখন এটি ব্যবহৃত হয় তখন ফাংশনটির নাম ধারণ করে একটি অক্ষর অ্যারে ভেরিয়েবলে প্রসারিত হয়। এটি সি 99 এ সি যুক্ত করা হয়েছিল। থেকে C99 §6.4.2.2 / 1:

শনাক্তকারীকে __func__অনুবাদকের দ্বারা স্পষ্টভাবে ঘোষণা করা হয়, তত্ক্ষণাত প্রতিটি ফাংশন সংজ্ঞা, প্রজ্ঞাপনের প্রারম্ভিক বন্ধনী অনুসরণ করে

static const char __func__[] = "function-name";

উপস্থিত হয়েছে, যেখানে ফাংশন-নাম লেক্সিক্যালি-এনক্লোজিং ফাংশনের নাম। এই নামটি ফাংশনের অলঙ্কৃত নাম।

মনে রাখবেন যে এটি কোনও ম্যাক্রো নয় এবং প্রিপ্রোসেসিংয়ের সময় এর কোনও বিশেষ অর্থ নেই।

__func__সি ++ এ সি ++ 11-এ যুক্ত করা হয়েছিল, যেখানে এটি "একটি বাস্তবায়ন-ডি-নেড স্ট্রিং" (সি ++ 11 §8.4.1 [dcl.fct.def.general] / 8) হিসাবে চিহ্নিত করা হয়েছে, যা যথেষ্ট নয় সি এর স্পেসিফিকেশন হিসাবে দরকারী ( __func__সি ++ যুক্ত করার মূল প্রস্তাবটি ছিল N1642 )।

__FUNCTION__একটি প্রাক-স্ট্যান্ডার্ড এক্সটেনশন যা কিছু সি সংকলক সমর্থন করে (জিসিসি এবং ভিজ্যুয়াল সি ++ সহ); সাধারণভাবে, আপনি __func__যেখানে এটি সমর্থিত সেখানে ব্যবহার করতে হবে এবং __FUNCTION__আপনি যদি কেবল এমন কোনও সংকলক ব্যবহার করেন যা এটি সমর্থন করে না (উদাহরণস্বরূপ, ভিজ্যুয়াল সি ++, যা C99 সমর্থন করে না এবং এখনও সমস্ত সি ++ 0x সমর্থন করে না, ব্যবহার করে না প্রদান __func__)।

__PRETTY_FUNCTION__একটি জিসিসি এক্সটেনশান যা বেশিরভাগের মতোই __FUNCTION__, সি ++ ফাংশন ব্যতীত এতে ফাংশনের স্বাক্ষর সহ ফাংশনের "সুন্দর" নাম রয়েছে। ভিজ্যুয়াল সি ++ এর সমান (তবে একরকম নয়) এক্সটেনশন রয়েছে __FUNCSIG__।

নন-স্ট্যান্ডার্ড ম্যাক্রোগুলির জন্য, আপনি আপনার সংকলকের ডকুমেন্টেশনের সাথে পরামর্শ করতে চাইবেন। সি ++ কম্পাইলারের "পূর্বনির্ধারিত ম্যাক্রোস" এর এমএসডিএন ডকুমেন্টেশনে ভিজ্যুয়াল সি ++ এক্সটেনশনগুলি অন্তর্ভুক্ত করা হয়েছে । Gcc ডকুমেন্টেশন এক্সটেনশনগুলি gcc ডকুমেন্টেশন পৃষ্ঠাতে "স্ট্রিং হিসাবে ফাংশন নাম" in


বিজয়ী উত্তরটির মতো দেখতে কীসের জন্য আপনি সি 99 স্পেসিফিকেশনটির (আপনার উত্সটিতে একটি ভাসমান লিঙ্ক আছে) লিঙ্ক করতে পারেন?
— ম্যাট যোগদানকারী

1
@ কিংবদন্তি 2 কে: না, এটি সি ++ 11 এ "একটি বাস্তবায়ন-সংজ্ঞায়িত স্ট্রিং"। স্পেসিফিকেশন থেকে এটি আসল ভাষা। §8.4.1 দেখুন [dcl.fct.def.general] / 8।
— জেমস ম্যাকনেলিস

2
মনে রাখবেন যে সিসিসি এবং ভিসি উভয়ই সরবরাহ করার সময় __FUNCTION__তারা কিছুটা আলাদা কাজ করে। gcc এর সমতুল্য দেয় __func__। উপাচার্য অজানা, কিন্তু এখনও শোভিত, নামের সংস্করণ দেয়। "ফু" নামের একটি পদ্ধতির জন্য, জিসিসি আপনাকে দেবে "foo", ভিসি দেবে "my_namespace::my_class::foo"।
— অ্যাড্রিয়ান ম্যাকার্থি

1
কৌতূহলোদ্দীপকটি হ'ল আমি এমএসভিসি 2017 সিই ব্যবহার করছি এবং আমি টাইপ করার সময় __PRETTY_FUNCTION__এটি তালিকাগুলিতে উপলব্ধ হিসাবে উপস্থিত হয় এবং যখন আমি এটির উপরে আমার মাউস সরিয়ে ফেলি তখন এটি ফাংশনটির নাম সম্পর্কিত তথ্য প্রদর্শন করে তবে এটি সংকলন করতে ব্যর্থ হয়।
— ফ্রান্সিস কিউলার

1
@ ফ্রেঞ্চিসকলারও আমি এতে অবাক হয়েছি! এটিতে আমার প্রশ্ন দেখুন stackoverflow.com/questions/48857887/…
— অ্যাডাম Badura

108

মূল প্রশ্নের পুরোপুরি উত্তর না দেওয়া সত্ত্বেও, সম্ভবত এটি বেশিরভাগ লোকেরা এটি দেখতে চেয়েছিল oo

জিসিসির জন্য:

petanb@debian:~$ cat test.cpp 
#include <iostream>

int main(int argc, char **argv)
{
    std::cout << __func__ << std::endl
              << __FUNCTION__ << std::endl
              << __PRETTY_FUNCTION__ << std::endl;
}
petanb@debian:~$ g++ test.cpp 
petanb@debian:~$ 
petanb@debian:~$ ./a.out 
main
main
int main(int, char**)

6
আমি জানি এটি একটি যথাযথ উত্তর নয় তবে সম্ভবত এটি যাঁরা গুগল করেছিলেন তারা সকলেই এটি দেখতে চেয়েছিল :) (যদি তারা নিজেরাই চেষ্টা করতে অলস হয়)
— পেট্র

5
ভাল কল, এটি দেখতে সুন্দর।
— ম্যাট জয়েনার


ঠিক আছে, তবে __func__যখন এটি অন্য ফাংশনটিতে এম্বেড করা থাকে তখন কাজ করে? বলি আমার ফাংশন 1 আছে এটি কোনও আর্গুমেন্ট নেয় না। ফাংশন 1 কল করে ফাংশন 2 যা অন্তর্ভুক্ত করে __func__, কোন ফাংশনটির নাম মুদ্রিত হবে, 1 বা 2?
— মারকাসজে

@ মার্কাসজে কেন নিজে চেষ্টা করবেন না ... এটি __func__একটি ম্যাক্রো, আপনি বর্তমানে যে কোনও ফাংশনে যাচ্ছেন তা এটি অনুবাদ করবে you আপনি যদি এটিকে F1 এ রেখে F2 এ f1 তে কল করেন তবে আপনি সর্বদা এফ 1 পাবেন।
— পেটর

41

__PRETTY_FUNCTION__ সি ++ বৈশিষ্ট্যগুলি পরিচালনা করে: শ্রেণি, নেমস্পেস, টেম্পলেট এবং ওভারলোড

main.cpp

#include <iostream>

namespace N {
    class C {
        public:
            template <class T>
            static void f(int i) {
                (void)i;
                std::cout << __func__ << std::endl
                          << __FUNCTION__ << std::endl
                          << __PRETTY_FUNCTION__ << std::endl;
            }
            template <class T>
            static void f(double f) {
                (void)f;
                std::cout << __PRETTY_FUNCTION__ << std::endl;
            }
    };
}

int main() {
    N::C::f<char>(1);
    N::C::f<void>(1.0);
}

সংকলন এবং চালান:

g++ -ggdb3 -O0 -std=c++11 -Wall -Wextra -pedantic -o main.out main.cpp
./main.out

আউটপুট:

f
f
static void N::C::f(int) [with T = char]
static void N::C::f(double) [with T = void]

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

উবুন্টু 19.04, জিসিসি 8.3.0 এ পরীক্ষিত।

সি ++ 20 std::source_location::function_name

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1208r5.pdf C ++ 20 এ গেছে, সুতরাং আমাদের এটি করার আর একটি উপায় আছে।

নথি বলছে:

কনস্টেক্সপ্রস কনট চর * ফাংশন_নাম () কনটেক্স নোসেকসেপ্ট;

6 রিটার্নস: যদি এই অবজেক্টটি কোনও ফাংশনের শরীরে কোনও অবস্থান প্রতিনিধিত্ব করে তবে একটি বাস্তবায়ন-সংজ্ঞায়িত এনটিবিএস প্রদান করবে যা ফাংশনের নামের সাথে মিল রাখে। অন্যথায়, একটি খালি স্ট্রিং প্রদান করে।

যেখানে এনটিবিএস অর্থ "নাল টার্মিনেটেড বাইট স্ট্রিং"।

সমর্থনটি জিসিসি, জিসিসি 9.1.0 এ পৌঁছানোর g++-9 -std=c++2aপরেও এটি ব্যবহার না করে চেষ্টা করব।

https://en.cppreferences.com/w/cpp/utility/source_location দাবী ব্যবহারের মতো হবে:

#include <iostream>
#include <string_view>
#include <source_location>

void log(std::string_view message,
         const std::source_location& location std::source_location::current()
) {
    std::cout << "info:"
              << location.file_name() << ":"
              << location.line() << ":"
              << location.function_name() << " "
              << message << '\n';
}

int main() {
    log("Hello world!");
}

সম্ভাব্য আউটপুট:

info:main.cpp:16:main Hello world!

সুতরাং এটি কীভাবে কলারের তথ্য ফেরত দেয় এবং লগিংয়ে ব্যবহারের জন্য নিখুঁত তা নোট করুন, আরও দেখুন: C ++ ফাংশনের ভিতরে ফাংশনের নাম পাওয়ার কোনও উপায় আছে কি?


13

__func__বিভাগ 8.4.1 এ সি ++ 0x স্ট্যান্ডার্ডে নথিভুক্ত করা হয়েছে। এক্ষেত্রে এটি ফর্মের একটি পূর্বনির্ধারিত ফাংশন স্থানীয় পরিবর্তনশীল:

static const char __func__[] = "function-name ";

যেখানে "ফাংশন নাম" বাস্তবায়ন স্পেসিফিক। এর অর্থ হ'ল আপনি যখনই কোনও ফাংশন ঘোষণা করেন, সংকলকটি আপনার ফাংশনে অন্তর্ভুক্তভাবে এই পরিবর্তনকটি যুক্ত করবে। একই __FUNCTION__এবং সত্য __PRETTY_FUNCTION__। তাদের বড়হস্ত হওয়া সত্ত্বেও, তারা ম্যাক্রোস নয়। যদিও __func__সি ++ 0x এর একটি সংযোজন

g++ -std=c++98 ....

এখনও কোড ব্যবহার করে সংকলন করবে __func__।

__PRETTY_FUNCTION__এবং __FUNCTION__এখানে নথিভুক্ত করা হয়েছে http://gcc.gnu.org/onlinesocs/gcc-4.5.1/gcc/Function-Names.html#Function-Names । __FUNCTION__এর অন্য একটি নাম __func__। সি __PRETTY_FUNCTION__হিসাবে একই __func__তবে সি ++ এ এতে স্বাক্ষর টাইপও রয়েছে।


__func__সি ++ 03 এর অংশ নয়। এটি সি ++ 0x এ যুক্ত করা হয়েছে, তবে সি ++ 0x এখনও "সি ++ স্ট্যান্ডার্ড নয়," এটি এখনও খসড়া আকারে রয়েছে।
— জেমস ম্যাকনেলিস

2
@ জেমস ম্যাকনেলিস এটি এখন, তাই মন্তব্যগুলি পরিষ্কার করুন, গোলমালটি সরাতে
— ডারামারাক

7

তাদের ক্ষেত্রে, যারা ভিসে এটি কীভাবে অবাক হয় wonder

এমএসভিসি 2015 আপডেট 1, cl.exe সংস্করণ 19.00.24215.1:

#include <iostream>

template<typename X, typename Y>
struct A
{
  template<typename Z>
  static void f()
  {
    std::cout << "from A::f():" << std::endl
      << __FUNCTION__ << std::endl
      << __func__ << std::endl
      << __FUNCSIG__ << std::endl;
  }
};

void main()
{
  std::cout << "from main():" << std::endl
    << __FUNCTION__ << std::endl
    << __func__ << std::endl
    << __FUNCSIG__ << std::endl << std::endl;

  A<int, float>::f<bool>();
}

আউটপুট:

প্রধান থেকে ():
প্রধান
প্রধান
int __cdecl main (বাতিল)

এ :: চ () থেকে:
একটি <কোন int, ভাসা> :: চ
চ
বাতিল

__PRETTY_FUNCTION__প্রত্যাশিত হিসাবে ট্রিগার অঘোষিত শনাক্তকারী ত্রুটি ব্যবহার করে ।

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