किसी फंक्शन को कॉन्सेप्ट पास करना


12

चूंकि अवधारणाओं को संकलन-समय की भविष्यवाणी के रूप में परिभाषित किया जाता है, क्या यह संकलन-समय के एल्गोरिदम के लिए वास्तव में इन विधेयकों का पुन: उपयोग करना संभव है? उदाहरण के लिए यह जाँचना संभव होगा कि क्या सभी प्रकार के टपल एक अवधारणा के अनुरूप हैं? जहां तक ​​मैंने देखा है कि किसी भी तरह से एक फंक्‍शन को कॉन्‍सेप्‍ट पास करना संभव नहीं है, जो इन मामलों के लिए टेम्‍प्‍लेट का उपयोग करके मुझे वापस ले जाता है।

#include <type_traits>

template<typename T>
concept FloatLike = std::is_same_v<T, float>;

struct IsFloat
{
    template<typename U>
    constexpr static bool test()
    {
       return FloatLike<U>;
    }
};


template<typename Predicate, typename... T>
constexpr bool all_types()
{
    return (Predicate::template test<T>() && ...);
}


int main()
{
   static_assert(all_types<IsFloat, float, float>());
   static_assert(!all_types<IsFloat, float, int>());
}

मैं जो करना चाहूंगा वह कुछ ऐसा है, इसलिए मुझे इसका इस्तेमाल करने में सक्षम होने के लिए हर समय अवधारणा को लपेटने की ज़रूरत नहीं है:

template<concept Predicate, typename... T>
constexpr bool all_types()
{
    return (Predicate<T> && ...);
}


int main()
{
   static_assert(all_types<FloatLike, float, float>());
   static_assert(!all_types<FloatLike, float, int>());
}

क्या इसके करीब जाने का कोई तरीका है?


और फिर अवधारणाओं की अवधारणाओं को जोड़ने का एक प्रस्ताव होगा ... BTW, all_types()गुना अभिव्यक्तियों का उपयोग करके काफी सरल बनाया जा सकता है ... &&:return (... && Predicate::template test<Ts>());
Evg

@ ईवीजी महान होगा :)
इगोर आर।

जवाबों:


5

क्या इसके करीब जाने का कोई तरीका है?

खैर, नहीं, वास्तव में नहीं। C ++ 20 में नहीं। टेम्पलेट अवधारणा-पैरामीटर की भाषा में आज कोई धारणा नहीं है। यहां तक ​​कि वेरिएबल टेम्प्लेट को टेम्प्लेट पैरामीटर के रूप में उपयोग नहीं किया जा सकता है। इसलिए अगर किसी अवधारणा को शुरू करना है, तो हम लपेटने से बच नहीं सकते।

लेकिन हम जो कर सकते हैं, वह है सरल आवरण। यदि हम "पुरानी शैली" प्रकार के गुणों का उपयोग करने के लिए सहमत होते हैं, विशेष रूप से जो कि std::integral_constantएस की तरह व्यवहार करते हैं , तो हम अपने आप को "अवधारणा" की परिभाषाओं के रूप में इस्तेमाल कर सकते हैं जो कि विधेय के रूप में इस्तेमाल किया जा सकता है।

template<typename T>
using FloatLike = std::is_same<T, float>;

template<template <typename> class Predicate, typename... T>
constexpr bool all_types()
{
    return (Predicate<T>{} && ...);
}

यह उतना ही अच्छा है जितना इसे मिल सकता है , जहां तक ​​मैं देख सकता हूं।


क्या यह किसी भी तरह से एक जेनेरिक लैंबडा को टेम्प्लेट टेम्पलेट घोषित करके काम करेगा? ऐसा लगता है कि लैम्ब्डा कभी भी टेम्प्लेट नहीं होता है, हालांकि केवल कॉल ऑपरेटर?
एंड्रियास लोंजोए

@AndreasLoanjoe - वास्तव में। एक लंबोदर कभी कोई टेम्प्लेट नहीं होता है। लेकिन अगर आप लैम्ब्डा पास करने के इच्छुक हैं, तो C ++ 20 आपको यह करने की अनुमति देता है। मैं कुछ ही मिनटों में इसका एक संस्करण जोड़ सकता हूं।
स्टोरीटेलर - अन्सलैंडर मोनिका

@AndreasLoanjoe - दूसरे विचार पर, एक लैम्ब्डा अभी भी बहुत क्रिया से बाहर आता है। मुझे नहीं लगता कि यह एक बढ़िया विकल्प है। यहाँ यह वैसे भी Godbolt.org/z/QSHy8X
StoryTeller - Unslander Monica

मुझे आशा है कि वे कुछ बेहतर जोड़ेंगे :), लेकिन हाँ ऐसा लगता है कि यह उत्तर है, केवल शैली प्रकार के लक्षण इस कार्यक्षमता अवधारणाओं की पेशकश करते हैं (अभी तक) नहीं।
एंड्रियास लोंजोए

0

यदि आपका लक्ष्य "यह देखना है कि क्या सभी प्रकार के एक अवधारणा के अनुरूप हैं" , तो आप कुछ इस तरह कर सकते हैं:

// concept to check if all types in Ts are the same as T
template<typename T, typename... Ts>
concept AllSame = (std::is_same_v<T,Ts> && ...);

// function only accepts floats as template parameters
template<AllSame<float>... Floats>
constexpr void float_foo()
{
}

// function only accepts ints as template parameters
template<AllSame<int>... Ints>
constexpr void int_foo()
{
}

// function only accepts T as template parameters
template<typename T, AllSame<T>... Ts>
constexpr void foo()
{
}

int main()
{
    int_foo<int, int, int>();
    // int_foo<int, int, double>(); // fails to compile
    float_foo<float, float, float>();
    // float_foo<float, float, int>(); // fails to compile
    foo<int, int, int, int>();
    // foo<int, int, int, float>(); // fails to compile
    foo<double, double, double, double>();
    // foo<double, double, double, int>(); // fails to compile

}

लाइव डेमो


आपका AllSameवैराग्य क्यों है ? एक प्रकार की बाधा द्वारा पेश किए गए पैक में प्रत्येक टेम्पलेट पैरामीटर अलग से पहले से ही विवश है।
डेविस हेरिंग 3

@DavisHerring मुझे समझ नहीं आ रहा है। क्या आप इस अवधारणा का अर्थ स्वयं या टेम्पलेट मापदंडों में हैं *_foo()?
kanstar

मेरा मतलब है कि कोड आप काम करता है, तो आप को दूर ...पर Tsऔर && ...यह का उपयोग करता है। (जाहिर है कि नाम AllSameतब अनुचित होगा, लेकिन मुझे यकीन नहीं है कि मैं क्यों किसी <int,int,int>भी तरह से एक गणना में व्यक्त करना चाहता हूं ।)
डेविस हेरिंग

@DavisHerring तब अवधारणा नहीं होगी AllSameलेकिन SameAs( en.cppreference.com/w/cpp/congets/same_as देखें ) और ओपी एक अवधारणा रखना चाहता था, जो कई प्रकार के टेम्पलेट मापदंडों को ले।
kanstar

जाहिर है कि यह होगा std::same_as। मुझे नहीं लगता कि वैरिएडिक हिस्सा बिंदु था: यह अवधारणा का (वांछित) परिवर्तनीय पहचान था। और मेरा कहना यह था कि आपके अवधारणा उदाहरण का वैरिएडिक पहलू इसके उपयोग के लिए अप्रासंगिक था (क्योंकि गैर-वैरिएड अवधारणाएं पहले से ही टेम्पलेट पैरामीटर पैक के साथ काम करती हैं)।
डेविस हेरिंग
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.