8

मैं IsLast टाइप गुणों को लिखने का प्रयास करता हूं यह जांचने के लिए कि std::tuple में दिया गया कोई अंतिम प्रकार है, लेकिन नीचे दिया गया कोड संकलित नहीं करता है। मुझे पता है कि इसके आसपास कैसे जाना है, लेकिन मुझे उत्सुकता है कि संकलक इसे क्यों पसंद नहीं करता है। मुझे लगता है कि वैरिएड-टेम्पलेट के विशेषज्ञता पर कुछ नियम होना चाहिए जो मुझे पता नहीं है। https://godbolt.org/g/nXdodxसी ++ टेम्पलेट आंशिक विशेषज्ञता: मैं आखिरी प्रकार में विविधता-टेम्पलेट में क्यों नहीं मिल सकता?

त्रुटि संदेश::

चेतावनी: वर्ग टेम्पलेट आंशिक विशेषज्ञता टेम्पलेट पैरामीटर नहीं कर सकते हैं शामिल हैं

error: implicit instantiation of undefined template 
'IsLast<std::tuple<std::__cxx11::basic_string<char>, int>, int>' 

वहाँ भी विशेषज्ञता घोषणा पर एक चेतावनी है

कोड पर है घटाया जाना; इस आंशिक विशेषज्ञता

#include <tuple> 
#include <string> 

/////////This works 
template<typename TP, typename T> 
struct IsFirst; 

template<typename U, typename ...V, typename T> 
struct IsFirst <std::tuple<U, V...>, T> 
{ 
    enum {value = false}; 
}; 

template<typename U, typename ...V> 
struct IsFirst <std::tuple<U, V...>, U> 
{ 
    enum {value = true}; 
}; 

////////This doesn't compile 
template<typename TP, typename T> 
struct IsLast; 

template<typename ...U, typename V, typename T> 
struct IsLast <std::tuple<U..., V>, T> 
{ 
    enum {value = false}; 
}; 

template<typename ...U, typename V> 
struct IsLast <std::tuple<U..., V>, V> 
{ 
    enum {value = true}; 
}; 


int main() 
{ 
    using T = std::tuple<std::string, int>; 
    bool v1 = IsFirst<T, std::string>::value; 
    bool v2 = IsLast <T, int>::value; 
} 
+9

मुझे विश्वास है कि विविध टेम्पलेट अंतिम आना चाहिए। – Resurrection

+1

आप किस कंपाइलर और संस्करण और संकलन झंडे का उपयोग कर रहे हैं? सटीक त्रुटि संदेश क्या है? –

+0

क्या आपका मतलब है कि "टाइपनाम ... यू" को आखिरी की तरह ले जाएं? यह अभी भी संकलित नहीं है। टेम्पलेट struct IsLast , टी> { enum {मूल्य = false}; }; –

उत्तर

8

इस्तेमाल किया जा कभी नहीं होगा एक वर्ग टेम्पलेट में, पैरामीटर पैक अन्य सभी टेम्प्लेट पैरामीटर के बाद आना चाहिए, तो कुछ इस तरह की अनुमति नहीं है।

template<typename U, typename ...V, typename T> 
struct IsFirst <std::tuple<U, V...>, T> 
{ 
    enum {value = false}; 
}; 

एक समारोह टेम्पलेट में, वहाँ पैक केवल अगर वे निष्कर्ष निकाला जा सकता है के बाद अन्य टेम्प्लेट पैरामीटर हो सकता है। कक्षा टेम्पलेट्स के लिए इसकी अनुमति नहीं है क्योंकि वे कटौती की अनुमति नहीं देते हैं।

#include <tuple> 
#include <string> 
#include <type_traits> 

int main() 
{ 
    using T = std::tuple<std::string, int>; 

    constexpr size_t size = std::tuple_size<T>::value; 

    typedef decltype(std::get<size - 1>(std::declval<T>())) LastType; 

    static_assert(std::is_same<std::decay_t<LastType>, int>::value, "no"); 

} 
+0

IsFirst वास्तव में काम करता है। यह इस्लास्ट है जो संकलित नहीं करता है। –

+0

मैं देखता हूं। मैंने आपका जवाब गलत तरीके से पढ़ाया। यह समझ में आता है। जवाब के लिए धन्यवाद। –

+0

आप गलत हैं। यह केवल तर्क सूची में है कि पैरामीटर पैक अंतिम होना चाहिए। मेरा जवाब पढ़ें। – Oliv

0

एक बेहतर समाधान नहीं है।

लेकिन एक ही परिणाम प्राप्त करने के कई अन्य तरीके हैं।

स्पष्ट समाधान एक पुनरावर्ती प्रकार लक्षण बनाने के लिए है, लेकिन मैं आपको std::tuple_element

#include <tuple> 
#include <iostream> 
#include <type_traits> 

template <typename C, typename T> 
struct IsLast; 

template <template <typename ...> class C, typename T, typename ... Ts> 
struct IsLast<C<Ts...>, T> 
{ 
    using Tl 
    = typename std::tuple_element<sizeof...(Ts)-1U, std::tuple<Ts...>>::type; 

    static constexpr bool value { std::is_same<Tl, T>::value }; 
}; 

int main() 
{ 
    using T = std::tuple<std::string, int>; 

    std::cout << IsLast<T, int>::value << std::endl; // print 1 
    std::cout << IsLast<T, long>::value << std::endl; // print 0 
} 

के आधार पर एक समाधान दिखा गौर करें कि

T = std::pairs<int, std::string> 

साथ और अन्य टेम्पलेट वर्गों के साथ इस IsLast काम करता है।

3

जी उठने द्वारा मनाया के रूप में, variadic टेम्पलेट अंतिम स्थिति में होना चाहिए:

2

संपादित करें: बोगदान टिप्पणी के लिए धन्यवाद, मानक उद्धरण अब सही है!

temp.deduct.type#9 के अनुसार:

पी के टेम्पलेट तर्क सूची एक पैकेट विस्तार है कि पिछले टेम्पलेट तर्क नहीं है शामिल है, तो पूरे टेम्पलेट तर्क सूची एक गैर निष्कर्ष निकाला संदर्भ

है ध्यान दें कि केवल तर्क टेम्पलेट की सूची है कि पैक अंतिम होना चाहिए। टेम्पलेट पैरामीटर पैक को टेम्पलेट पैरामीटर सूची में अंतिम होने की आवश्यकता नहीं है, यह टेम्पलेट क्लास आंशिक विशेषज्ञता या टेम्पलेट फ़ंक्शंस का मामला हो सकता है।

तो वर्ग टेम्पलेट आंशिक विशेषज्ञता के अपने पहले उदाहरण सही है:

template<typename U, typename ...V> 
struct IsFirst <std::tuple<U, V...>, U> 
{ 
    enum {value = true}; 
} 

क्योंकि V...tuple के अंतिम तर्क है।

template<typename ...V,typename U> 
struct IsFirst <std::tuple<V..., U>, U> 
{ 
    enum {value = true}; 
}; 

क्योंकि V...tuple के अंतिम तर्क नहीं है।

+0

यह पैराग्राफ आंशिक विशेषज्ञता की टेम्पलेट तर्क सूची पर लागू होता है, न कि विशेषज्ञता के तर्कों की नेस्टेड टेम्पलेट तर्क सूचियों के लिए। इस मामले में क्या लागू होता है [\ [temp.deduct.type \]/9] (http://eel.is/c++draft/temp.deduct.type#9): "यदि टेम्पलेट तर्क सूची पी में एक पैक विस्तार शामिल है जो अंतिम टेम्पलेट तर्क नहीं है, संपूर्ण टेम्पलेट तर्क सूची एक गैर-कटौती संदर्भ है। " यह प्रश्न में उल्लिखित संकलक संदेश के अनुरूप है। – bogdan

+0

धन्यवाद! मैं जवाब संपादित करता हूं। – Oliv

संबंधित मुद्दे