আমি কীভাবে দ্বিতীয় টেম্পলেট যুক্তি অনুমান করে সি ++ প্রতিরোধ করতে পারি?


26

আমি একটি সি ++ গ্রন্থাগার ( স্ট্র্যাফ ) ব্যবহার করছি যা এর মধ্যে কোথাও নীচের কোড রয়েছে:

namespace strf {
template <typename ForwardIt>
inline auto range(ForwardIt begin, ForwardIt end) { /* ... */ }

template <typename Range, typename CharT>
inline auto range(const Range& range, const CharT* sep) { /* ... */ }
}

এখন, আমি strf::range<const char*>(some_char_ptr, some_char_ptr + some_length)আমার কোড ব্যবহার করতে চাই তবে আমি যদি এটি করি তবে আমি নিম্নলিখিত ত্রুটিটি পেয়েছি (সিইউডিএ 10.1 এর এনভিসিসি সহ):

error: more than one instance of overloaded function "strf::range" matches the argument list:
            function template "auto strf::range(ForwardIt, ForwardIt)"
            function template "auto strf::range(const Range &, const CharT *)"
            argument types are: (util::constexpr_string::const_iterator, util::constexpr_string::const_iterator)

গ্রন্থাগার কোড সম্ভবত এই (যেমন ব্যবহার এড়াতে পরিবর্তন করা যাবে:

inline auto range(const typename std::enable_if<not std::is_pointer<typename std::remove_cv<Range>::type>::value, Range &>::type range, const CharT* sep)

নিশ্চিত Rangeকরা কোনও পয়েন্টার নয়); তবে আমি এখনই এই পরিবর্তন করতে পারি না। পরিবর্তে, আমি কোনওভাবে সংকলককে ইঙ্গিত করতে চাই যে আমি সত্যই বলতে চাইছি কেবলমাত্র একটি নির্দিষ্ট টেমপ্লেট যুক্তি রয়েছে, একটি নির্দিষ্ট নয় এবং অন্যটিকে ছাড় দেওয়া হয়েছে।

আমি কি এটা করতে পারি?

সি ++ 11 এবং সি ++ 14 এর জন্য উত্তরগুলি প্রশংসা করবে; C ++ 17 টি উত্তর কাটা গাইডের সাথে জড়িত কম প্রাসঙ্গিক তবে আপনার যদি একটি থাকে তবে দয়া করে এটি পোস্ট করুন (ভবিষ্যতের এনভিসিসি সংস্করণের জন্য ...)


আপডেট: স্ট্র্যাফ লাইব্রেরি নিজেই এই পরিস্থিতি থেকে বাঁচানোর জন্য আপডেট করা হয়েছে, তবে প্রশ্ন যেমন রয়েছে তেমন দাঁড়িয়েছে।


1
আমি অনুমান করছি যে একটি কাস্টম পুনরাবৃত্তকারী যা উত্তমরূপে একটি মোড়ানো char*তবে একটি সমাধান নয়?
কনরাড রুডল্ফ

1
@ কনরাড রুডল্ফ: এটি একটি কার্যকরী, তবে আমার প্রশ্নের উত্তর দেয় না। আমার কাছে ইতিমধ্যে অন্য একটি কাজ রয়েছে (/*...* / এ থাকা সুনির্দিষ্ট) তবে আমি এখানে উচ্চতর রাস্তাটি নিতে চাই।
einpoklum

1
সেক্ষেত্রে আমার (অনুমান করা) উত্তরটি "করা যায় না" দুর্ভাগ্যক্রমে। ন্যায্য বলতে আমি নিশ্চিত নই যে আমি আমার নিজস্ব কোডটিতে প্রস্তাবিত কাজটি গ্রহণ করব।
কনরাড রুডলফ

কেবল স্পষ্ট করে বলতে: আপনি কি একটি সাধারণ সমাধান চান, এটি সর্বদা একটি বনাম দুটি পরামিতি সহ টেম্পলেট ওভারলোডগুলির মধ্যে একটি কলকে পৃথক করার জন্য কাজ করবে বা আপনি এই ক্ষেত্রে কেবলমাত্র কোনও সমাধান চান?
আখরোট

@ আখরোট: সাধারণ সমাধান আরও ভাল হবে; আমার নির্দিষ্ট দৃশ্যটি বেশিরভাগই সমস্যার জন্য অনুপ্রেরণা।
einpoklum

উত্তর:


16
template<typename T>
inline constexpr auto range1_ptr = strf::range<T>;

template<typename T>
inline decltype(auto) range1(T begin, T end) {
    return range1_ptr<T>(begin, end);
}

range1তার পরিবর্তে কল করুন strf::range

range1_ptr<T>(...)সর্বদা স্পষ্টভাবে একটি টেম্পলেট যুক্তি গ্রহণ করে টেম্পলেট কল করতে ব্যবহৃত হতে পারে, কিন্তু আর্গুমেন্ট থেকে কোনও ছাড় নেই। range1মূল strf::rangeটেম্পলেট থেকে ছাড়ের প্রতিলিপি করে ।

এটি কাজ করে, কারণ [টেম্পেডাক্ট.ফুনক্যাড্ডার] / ১ বলেছেন যে কোনও ধরণের রূপান্তরের লক্ষ্যমাত্রা ছাড়াই কোনও ফাংশনের ঠিকানা গ্রহণের সময় টেম্পলেট আর্গুমেন্ট ছাড় খালি। সুতরাং দ্বিতীয় টেমপ্লেট আর্গুমেন্টটি দুটি টেমপ্লেট পরামিতি সহ দ্বিতীয় ওভারলোডের জন্য হ্রাস করা যায় না। একমাত্র প্রার্থী হ'ল প্রথম ওভারলোড, যা ফাংশন পয়েন্টারের লক্ষ্য হিসাবে বেছে নেওয়া হবে।

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


সম্পর্কে অস্পষ্টতা থাকবে না strf::range<T>?
einpoklum

1
@ আইনপোকলুম এটি জিসিসি এবং কলংয়ের জন্য সূক্ষ্ম সংকলন করে। আমি স্ট্যান্ডার্ডটি যাচাই করিনি, তবে যদি তা অস্পষ্ট হওয়ার কথা মনে হয় তবে অবাক হব।
আখরোট

হতে পারে আপনি ফাংশন নাম পরিবর্তন করা উচিত pretty_please_with_sugar_on_top()? ... সি ++ কখনও কখনও এত অদ্ভুত হতে পারে ...
einpoklum

আপনি গ্রহণযোগ্য উত্তরটি
আনসেট

11

একটি মাধ্যমে পাস সম্পর্কে কি using?

using tfp = void(*)(char const *, char const *);

tfp x = &strf::range;

char const * a = "abcd";

(*x)(a, a+2);

এবং এই সংকলন? দ্বিতীয় লাইনটি বিশেষত সন্দেহজনক দেখাচ্ছে।
einpoklum

@ আইনপোকলুম - মজার, তাই না?
সর্বোচ্চ 66

@ আইনপোকলুম - দুর্ভাগ্যক্রমে কোনও সাধারণ সমাধান নয়; এই ক্ষেত্রে কাজ করে কারণ (যদি আমি ভুল না হয়) কেবলমাত্র প্রথম range()সংস্করণটি সামঞ্জস্যপূর্ণ tpf; অন্য ক্ষেত্রে ভিন্ন হতে পারে।
সর্বোচ্চ 66

@ আইনপোকলুম - দ্বিতীয় লাইনে আপনি টেম্পলেট প্যারামিটারটিও ব্যাখ্যা করতে পারেন ( tfp x = &strf::range<char const *>;); এইভাবে আমি মনে করি আপনার কাছে একটি সাধারণ সমাধান রয়েছে, প্রায় আখরোটের সমান
ম্যাক্স6666

0

একটি সমাধান হয়

1) সবার আগে, আপনার দ্বিতীয় যুক্তির জন্য ধরণ উল্লেখ করা উচিত, যেমন (char *)(some_char_ptr + some_length)

2) constউভয়ের জন্য ব্যবহার করবেন না , এটি ভালভাবে কাজ করে:

strf::range((char *)some_char_ptr, (char *)(some_char_ptr + some_length));

আপনি প্রতিস্থাপন করার চেষ্টা করতে পারেন (char *)সঙ্গে (const char *)বাম বা ডান দিকে, এটা এখনও কাজ করে।


যদি আর্গুমেন্টগুলি constডেটাতে নির্দেশ করে তবে এটি বেশ কুৎসিত ।
aschepler

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