2017-09-07 19 views
14

मेरे पास इस कोड के लिए अजीब आउटपुट क्यों है? एक प्रकार के लिए सही तरीके से परीक्षण कैसे करें?यह पता लगाने के लिए कि कोई प्रकार std :: tuple है या नहीं?

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

template<typename T> struct is_tuple : std::false_type {}; 
template<typename... Ts> struct is_tuple<std::tuple<Ts...>> : std::true_type {}; 

struct TraitBlock { 
    using BlockLocation = struct { std::uint64_t x, y, z; }; 
}; 

struct TraitRock {}; 

struct ItemTemplate{ 
    static constexpr auto traits = std::make_tuple(
     TraitBlock{}, 
     TraitRock{} 
    ); 
}; 

int main(){ 
    using A = std::tuple<char, int,double,char>; 
    std::cout << is_tuple<decltype(ItemTemplate::traits)>::value 
    << is_tuple<decltype(std::make_tuple(
     TraitBlock{}, 
     TraitRock{} 
    ))>::value 
    << std::endl; 
} 

मैं -std साथ mingw64-जीसीसी 7.2.0 का उपयोग = C++ 17, मुझे मिल उत्पादन "01" क्यों मैं दो अलग-अलग उत्पादन मिल गया? क्या वे एक ही प्रकार के नहीं हैं?

+3

आप टेम्पलेट स्ट्रक्चर डमी जैसे कुछ उपयोग कर सकते हैं; टेम्पलेट स्ट्रक्चर डमी ; 'कंपाइलर को आपको त्रुटि संदेश में प्रकार देने देता है। – Jarod42

उत्तर

16

decltype(ItemTemplate::traits)const std::tuple<TraitBlock, TraitRock> है।

तो आपको कहीं सीवी क्वालीफायर को संभालना होगा।

+0

ओह, constexpr का मतलब है, लेकिन जब मैं constexpr का उपयोग करता हूं, तो यह भीतरी प्रकार के make_tuple const बना देगा? –

+1

यह सुनिश्चित नहीं है कि आपका क्या मतलब है, लेकिन आपके पास 'std :: tuple ' है, न कि stst :: tuple '। – Jarod42

12

ध्यान दें कि ItemTemplate::traits के प्रकार (अर्थात decltype(ItemTemplate::traits)) const std::tuple<TraitBlock, TraitRock> है, जो is_tuple की विशेषज्ञता में निर्दिष्ट प्रकार (अर्थात std::tuple<Ts...>) से मेल नहीं खाता।

आप std::remove_const द्वारा कॉन्स्ट-नेस को हटा सकते हैं, उदा।

std::cout << is_tuple<std::remove_const_t<decltype(ItemTemplate::traits)>>::value; 

या const के लिए एक और विशेषज्ञता को जोड़ने (और साथ ही volatile हो सकता है):

template<typename... Ts> struct is_tuple<std::tuple<Ts...>> : std::true_type {}; 
template<typename... Ts> struct is_tuple<const std::tuple<Ts...>> : std::true_type {}; 
template<typename... Ts> struct is_tuple<volatile std::tuple<Ts...>> : std::true_type {}; 
template<typename... Ts> struct is_tuple<const volatile std::tuple<Ts...>> : std::true_type {}; 
7

आप सभी क्वालिफायर दूर करने के लिए की जरूरत है। इसे स्वयं करने के बजाय आपको std::decay_t का उपयोग करना चाहिए जो आपके लिए सभी क्वालीफायर हटा देता है और आपकी विशेषता को प्रेषित करता है। उदाहरण के लिए

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

template<typename... Ts> 
struct is_tuple_impl<std::tuple<Ts...>> : std::true_type {}; 

template<typename T> 
struct is_tuple : is_tuple_impl<std::decay_t<T>> {} 
+1

क्या आपका मतलब 'std :: decay_t' के बजाय' std :: remove_cv_t' नहीं है? – Caleth

+3

यह निर्भर करता है, 'remove_cv_t' 'decay_t' का सबसेट है। उत्तरार्द्ध भी संदर्भों (आर- और एल-वैल्यू) को हटा देगा जो आम तौर पर लक्षणों के लिए भी आवश्यक है। जब तक आप 'std :: tuple <…> और' और 'std :: tuple <…> &&' नहीं ढूंढना चाहते हैं। –

+0

आमतौर पर, हम 'std :: tuple <> &' tuple होने पर विचार नहीं करते हैं। यह सामान्य तरीका है काम करता है। – Barry

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

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