টেমপ্লেটগুলি ব্যবহার করে একটি ফাংশন ওভারলোড হচ্ছে


34

আমি টেমপ্লেটগুলি ব্যবহার করে কোনও ফাংশন সংজ্ঞায়িত করার চেষ্টা করছি এবং আমি চাই টাইপনামটি হয় হয় ইনট বা এ্যানুম (একটি নির্দিষ্ট এনাম যা আমি সংজ্ঞায়িত করেছি)। আমি নিম্নলিখিত চেষ্টা করেছিলাম কিন্তু আমি ব্যর্থ হয়েছি:

template <int | anEnum T> // or <int T, anEnum T> or <int, anEnum T>
bool isFunction(const T &aVariable){}

আমি যা করার চেষ্টা করছি তা হল দুটি ওভারলোডেড ফাংশন সংজ্ঞায়নের পরিবর্তে টেমপ্লেটগুলি ব্যবহার করা। প্রোগ্রামারটির ধরণটি বিবেচনা না করেই আমি ফাংশনটিকে নিম্নলিখিত হিসাবে ডাকা পছন্দ করব

isFunction(aVariable) // and not isFunction<int> (aVariable) nor isFunction<anEnum> (aVariable)

মূলত, আমি চাই এই ফাংশনটি int এবং aNum ধরণের জন্য প্রেরণিত করা হোক। আমি এটি অনুসন্ধান করেছি, কিন্তু উত্তর খুঁজে পাইনি। আমি কী মিস করছি? ধন্যবাদ,


যদি এটি হুবহু একক এনাম বা টাইপ ইন্ট হয় তবে কেন উভয় ফাংশন সহজভাবে লিখবেন না? সেক্ষেত্রে আপনার কেন একটি টেম্পলেট দরকার?
ক্লাউস

অন্যান্য ধরণের কী হবে? আপনি কি falseঅন্য ধরণের জন্য ফিরে আসতে চান বা অন্য ধরণের জন্য ফাংশনটি ইনস্ট্যান্ট না করতে চান।
ব্যাঙ্গোত্তো

@ ফ্রোগাটো না, বুল রিটার্ন মানটির সাথে প্রকারের কিছু নেই।
বিজি

@ ক্লাউস আমি বিকল্পগুলি শিখতে বলেছি। বর্তমান উত্তরের উপর ভিত্তি করে, আমি উভয় ফাংশনকে কেবল সংজ্ঞায়িত করার সিদ্ধান্ত নিয়েছি।
বিজি

উত্তর:


25

নন-সি ++ ২০ টি উত্তর ছাড়াও, আপনি যদি কোনও সুযোগে সি ++ 20 এবং এর conceptsবৈশিষ্ট্যটি ব্যবহার করতে সক্ষম হন তবে আমি আপনাকে নিম্নলিখিত প্রয়োগের পরামর্শ দিচ্ছি:

#include <iostream>
#include <concepts>

enum class MyEnum {
    A,
    B,
    C
};

template <typename T>
concept IntegralOrEnum = std::same_as<MyEnum, T> || std::integral<T>;

template <IntegralOrEnum T>
bool isFunction(T const& aVariable) {
    return true;
}

int main() {
    isFunction(MyEnum::A);
    isFunction(3);
    isFunction("my_string"); // error
    return 0;
}

ডেমো

হালনাগাদ

@ রিচার্ডস্মিথের মন্তব্য অনুসারে , এখানে আরও একটি স্কেলযোগ্য এবং পুনরায় ব্যবহারযোগ্য পদ্ধতি:

template <typename T, typename ...U>
concept one_of = (std::is_same_v<T, U> || ...);

template <one_of<int, MyEnum> T>
bool isFunction(T const& aVariable) {
    return true;
}

প্রকারটি দুটি নির্দিষ্ট ধরণের মধ্যে একটি হওয়ার প্রয়োজনের নির্দিষ্ট ক্ষেত্রে, এর মতো আরও ভাল কিছু কাজ করতে পারে:template<typename T, typename ...U> concept one_of = (std::is_same_v<T, U> || ...); template<one_of<int, MyEnum> T> bool isFunction(T const& aVariable) {
রিচার্ড স্মিথ

1
@ রিচার্ডস্মিথ আমিও তার সাথে আমার উত্তর আপডেট করেছি। আমি এটি আরও পুনরায় ব্যবহারযোগ্য এবং স্কেলযোগ্য মনে করি। ধন্যবাদ
নটক্র্যাকার

21

এটি সম্পাদন করার কয়েকটি উপায় রয়েছে। সমস্ত শিরোনাম ব্যবহার করে জড়িত type_traits। উদাহরণস্বরূপ, আপনি ফাংশনটির শৃঙ্খলে থাকা প্রশ্নগুলির প্রকারগুলিতে স্থির থাকতে পারেন।

অথবা, যদি আপনাকে অন্যান্য ওভারলোডগুলির মধ্যে এই ফাংশনটি বিবেচনা করার প্রয়োজন হয় তবে একটি SFINAE কৌশল ব্যবহার করা যেতে পারে।

template<typename T>
auto isFunction(const T &aVariable) 
  -> std::enable_if_t<std::is_same<T, int>::value || std::is_same<T,anEnum>::value, bool> {
}

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


3

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

#include <type_traits>
enum anEnum {
    //
};

template <typename T, bool defined = std::is_same<T, int>::value ||
                                     std::is_same<T, anEnum>::value>
bool isFunction(const T& aVariable)
{
    static_assert(defined, "Invalid specialization");

    bool result = false;
    // Put your code here
    return result;
}

1
যদি সেখানে অন্যান্য স্বাক্ষর উপস্থিত থাকে (যেমন, একটি অনুমানমূলক isFunction(std::string_view)) থাকে তবে এটি ওভারলোড রেজোলিউশনের সাথে ভালভাবে কাজ করে না । স্বাক্ষরটি এখনও একটি বৈধ ম্যাচ হবে তবে তাত্ক্ষণিক কারণে ত্রুটি ঘটায়।
এলএফ

আপনি মুছে ফেলা হিসাবে অকেজো স্বাক্ষর ঘোষণা করতে পারেন: bool isFunction (std :: string_view) = মুছুন;
ixjxk

আমি অতিরিক্ত ওভারলোড সম্পর্কে কথা বলছি সেক্ষেত্রে এই অবৈধ স্বাক্ষরটি হুবহু মিল হতে পারে (উদাহরণস্বরূপ, স্ট্রিং লিটারেলের জন্য), ফলে ওভারলোডকে অবরুদ্ধ করে।
এলএফ

0

আমি https://stackoverflow.com/a/60271100/12894563 উত্তর উন্নত করেছি । 'কনস্টেক্সপ্র' যদি এই পরিস্থিতিতে সহায়তা করতে পারে:

template <typename T>
struct always_false : std::false_type {};

template <typename T>
bool isFunction(const T& aVariable)
{
    if constexpr(std::is_same_v<T, int> || std::is_same_v<T, anEnum>)
    {
        std::cout << "int\n";
        // put your code here
        return true;
    }
    else
    {
        static_assert(always_false<T>::value, "You should declare non-template function or write if constexpr branch for your type");
        return false;
    }
}

bool isFunction(std::string_view)
{
    std::cout << "std::string_view\n";
    return true;
}

int main()
{
    isFunction(std::string_view("1L"));
    isFunction(1);
    //isFunction(1L); // will produce an error message from static_assert
}

isFunction (1L) ব্যর্থ হবে কারণ ওভারলোডেড ফাংশন বা 'কনস্টেক্সপ্র' শাখা নেই।

আপডেট: ফিক্সড মিস

template <typename T>
struct always_false : std::false_type {};

https://godbolt.org/z/eh4pVn


static_assert(false, ...)এমনকি ব্যবহার না করেই দুর্গঠিত এনডিআর। আপনি যদি ভাগ্যবান হন তবে আপনার সংকলকটি এখনই
জেড / এম_জিকি 9 এন - স্টোরি টেলার - আনস্ল্যান্ডার মনিকা

আপনার মন্তব্যের জন্য অনেক ধন্যবাদ, আমি একটি ভুল করেছি। স্থির, Godbolt.org/z/eh4pVn
ixjxk
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.