কোনও ফাংশনের ধরণের আর্গুমেন্টের জন্য টেমপ্লেট আর্গুমেন্ট ছাড়


10

নিম্নলিখিত প্রোগ্রাম বিবেচনা করুন।

#include <iostream>

template <typename T>
void f( void ( *fn )( T ) )
{
    fn( 42 );
}

void g( int x )
{
    std::cout << "g( " << x << " );\n";
}

int main()
{
    f( g );
}

প্রোগ্রামটি সফলভাবে সংকলন করে এবং এর আউটপুট হয়

g( 42 );

এখন অ টেমপ্লেট ফাংশন নামান্তর দিন gথেকে f

#include <iostream>

template <typename T>
void f( void ( *fn )( T ) )
{
    fn( 42 );
}

void f( int x )
{
    std::cout << "f( " << x << " );\n"; 
}

int main()
{
    f( f );
}

এখন প্রোগ্রামটি gcc হেড 10.0.0 20200 দ্বারা সংকলিত হয়নি এবং ঝনঝন হেড 10.0.0 দ্বারা নয় তবে ভিজ্যুয়াল সি ++ 2019 দ্বারা সাফল্যের সাথে সংকলিত হয়েছে ..

উদাহরণস্বরূপ সংকলক জিসিসি নিম্নলিখিত বার্তাগুলির সেট জোগায়।

prog.cc: In function 'int main()':
prog.cc:22:10: error: no matching function for call to 'f(<unresolved overloaded function type>)'
   22 |     f( f );
      |          ^
prog.cc:4:6: note: candidate: 'template<class T> void f(void (*)(T))'
    4 | void f( void ( *fn )( T ) )
      |      ^
prog.cc:4:6: note:   template argument deduction/substitution failed:
prog.cc:22:10: note:   couldn't deduce template parameter 'T'
   22 |     f( f );
      |          ^
prog.cc:14:6: note: candidate: 'void f(int)'
   14 | void f( int x )
      |      ^
prog.cc:14:13: note:   no known conversion for argument 1 from '<unresolved overloaded function type>' to 'int'
   14 | void f( int x )
      |         ~~~~^

সুতরাং একটি প্রশ্ন ওঠে: কোডটি সংকলন করা উচিত এবং কী কারণে কোডটি জিসিসি এবং ঝনঝন দ্বারা সংকলিত হয়নি?



দ্রষ্টব্য: প্রথম উদাহরণে, ফাংশন টেমপ্লেটে g(পরিবর্তে &g) পাস করার ফলে টাইপ ক্ষয় হয় (একটি ফাংশন অবলম্বন রেফারেন্স একটি ফাংশনের দিকে নির্দেশকের ক্ষয়ে যায়: void(&)(T)=> void(*)(T))। এই প্রকৃত রূপান্তরটি ঘটে কারণ fআরও ভাল কোনও মিলের সাথে আর কোনও ওভারলোড নেই । দ্বিতীয় উদাহরণে, একটি দ্ব্যর্থতা আছে যা fআপনি আসলে কল করতে চান কারণ ... এটি জানে না কোনটি fযুক্তি।
Xeverous

উত্তর:


7

এটি আমার কাছে মনে হবে যে জিসিসি এবং ঝনঝন সঠিক। এটি সংকলন করা উচিত নয়। আপনি যে ফাংশনটি প্যারামিটারটি থেকে Tকমিয়ে নিতে চান তা এখানে একটি অ- ছাড় ছাড়াই প্রসঙ্গে পরিণত হয় এখানে যে মুহূর্তে যুক্তি সরবরাহ করা হয়েছে এমন একটি ওভারলোড সেট যা একটি ফাংশন টেম্পলেট [টেম্পেডাক্ট.টাইপ] /5.5 রয়েছে :

অ-অনুদানপ্রাপ্ত প্রসঙ্গগুলি হ'ল:

  • [...]
  • একটি ফাংশন প্যারামিটার যার জন্য আর্গুমেন্ট কর্তন করা যায় না কারণ সম্পর্কিত ফাংশন আর্গুমেন্ট একটি ফাংশন, বা অতিরিক্ত লোড ফাংশনগুলির একটি সেট ([over.over]), এবং নিম্নলিখিত এক বা একাধিক প্রয়োগ হয়:

    • [...]
    • আর্গুমেন্ট হিসাবে সরবরাহিত ফাংশনগুলির সেটটিতে এক বা একাধিক ফাংশন টেম্পলেট রয়েছে।
  • [...]

সুতরাং, Tকোনও রূপান্তর না হওয়ার কারণে ছাড় দেওয়া যায় না এবং অন্যান্য ওভারলোডটি কার্যকর হয় না; জিসিসি ঠিক কী বলে ...


0

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

void f( void ( *fn )( int ) ){
  fn( 42 );
}
void f( int x ){
    std::cout << "f( " << x << " );\n";
  }

  int main(){

     f( f );
  }

ওভারলোড রেজোলিউশনের সময় অন্যথায় কোনও টাই থাকলে নন-টেম্পলেট ফাংশনগুলি অগ্রাধিকার দেওয়া হয়। প্রশ্নের কোডটি এই পর্যায়ে void f<int>(void(int))পৌঁছায় না: উভয় স্তরে ওভারলোড রেজোলিউশন করার জন্য কোনও বিশেষীকরণ কখনও তৈরি হয় না ।
ডেভিস হেরিং
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.