2017-04-19 9 views
15

जब कस्टम प्रकार लक्षण लेखन, मैं अक्सर उन्हें मानक पुस्तकालय प्रकार लक्षण से निकाले जाते हैं इस प्रकार है:मानक पुस्तकालय प्रकार से विरासत लक्षण

template<typename T> 
struct some_type_trait: 
    std::is_arithmetic<T> 
{}; 

हालांकि, मैं कभी-कभी आश्चर्य मानक के type सदस्य प्रकार से इनहेरिट कि क्या पुस्तकालय प्रकार विशेषता क्लीनर है:

template<typename T> 
struct some_type_trait: 
    std::is_arithmetic<T>::type 
{}; 

समग्र विचार यह है कि अंत में std::bool_constant मामलों से केवल विरासत है, लेकिन तथ्य यह है कि हम पहले उदाहरण में std::is_arithmetic से इनहेरिट रहे हैं और std::bool_constant (जैसा कि दूसरे मामले में) से सीधे नहीं है polymorphism या utilies के माध्यम से std::is_base_of के माध्यम से देखा जा सकता है।

सार है कि type सदस्य प्रकार के माध्यम से bool_constant से सीधे विरासत में क्लीनर का मानना ​​है, क्योंकि यह बिल्कुल है कि हम क्या करना चाहते हैं। हालांकि, std::is_arithmetic से विरासत में थोड़ा छोटा है और अनिवार्य रूप से वही व्यवहार प्रदान करता है। तो ... क्या कोई सूक्ष्म लाभ है कि एक या दूसरे (सहीता, संकलन समय ...) चुनते समय मुझे याद आ रही है? क्या सूक्ष्म परिदृश्य हैं जहां std::is_arithmetic से उत्तराधिकारी अंतर्निहित bool_constant से सीधे विरासत की तुलना में, एप्लिकेशन के व्यवहार को बदल सकता है?

+6

यह कुछ गुणवत्ता बाइकहेडिंग है: डी – Rerito

+0

एफडब्ल्यूआईडब्ल्यू, en.cppreference.com पर "संभावित कार्यान्वयन" सीधे 'std :: integral_constant ' का उत्तराधिकारी है। इस "शैली" के बाद आपका उदाहरण 'std :: integral_constant :: value>' से प्राप्त होगा। –

+0

@DanielJour अगर मुझे गलत नहीं लगता है, तो टाइप विशेषता के लिए 'std :: integral_constant' से विरासत अनिवार्य है। सवाल यह है कि क्या टाइपिंग विशेषता के माध्यम से ':: टाइप' या परोक्ष रूप से' std :: integral_constant' से सीधे प्राप्त करना बेहतर है या नहीं। हो सकता है कि मैं आपकी टिप्पणी को समझ नहीं पा रहा हूं:/ – Morwenn

उत्तर

1

दूसरा कार्यान्वयन विवरण लीक करने का मामूली नुकसान है; यदि आप is_arithmetic<int> या जो कुछ भी प्राप्त करते हैं, तो कोई फ़ंक्शन ओवरलोड के माध्यम से परीक्षण कर सकता है। यह "काम" कर सकता है और झूठी सकारात्मकताओं का कारण बन सकता है।

यह एक मामूली मामूली मुद्दा है।

यदि आपका कंपाइलर बेस क्लास नाम डंप करता है तो आपको is_arithmetic से विरासत में थोड़ा बेहतर डायग्नोस्टिक्स मिल सकता है।

आपके डिजाइनों में से कोई भी अच्छी तरह से लिखता है। इसके बजाए:

template<class T> 
struct some_type_trait: 
    std::integral_constant<bool, 
    std::is_arithmetic<T>{} 
    > 
{}; 

बढ़ाया जा सकता है, क्योंकि हम वहां कोई अभिव्यक्ति डाल सकते हैं।

जैसा कि मैंने पहले बताया गया है, प्रकार के होने त्रुटि संदेश में सहायक हो सकता है, तो हम कर सकता है:

constexpr bool all_of() { return true; } 
template<class...Bools> 
constexpr bool all_of(bool b0, Bools...bs) { 
    return b0 && all_of(bs...); 
} 
template<class T, template<class...>class...Requirements> 
struct Requires : std::integral_constant<bool, 
    Requirements<T>{} &&... 
    // in C++11/14, something like: all_of(Requirements<T>::value...) 
> {}; 

तो हम पाते हैं:

template<class T> 
using some_type_trait = Requires<T, std::is_arithmetic>; 

अगर यह एक खोजने के लिए विफल रहता है जो एक टैग प्रेषण में अधिभार, एक त्रुटि उत्पन्न करेगा जो आपको एक सुराग दे सकता है।

template<class T> 
void test(std::true_type passes_test, T t) { 
    std::cout << t+0 << "\n"; 
} 
template<class T> 
void test(T t) { 
    return test(some_type_trait<T>{}, t); 
} 
int main() { 
    test(3); 
    test("hello"); 
} 

दुर्भाग्य से हम टेम्पलेट metaprogramming में currying/आसान बाध्यकारी/आंशिक आवेदन के बराबर नहीं है। तो f<.> = is_base_of<X, .> को स्पष्ट रूप से व्यक्त करना मुश्किल है।

Live example, त्रुटि संदेश हम प्राप्त है: बजना:

main.cpp:23:10: note: candidate function [with T = const char *] not viable: no known conversion from 'some_type_trait<const char *>' (aka 'Requires<const char *, std::is_arithmetic>') to 'std::true_type' (aka 'integral_constant<bool, true>') for 1st argument 

जीसीसी:

main.cpp:28:18: note: cannot convert 'Requires<const char*, std::is_arithmetic>()' (type 'Requires<const char*, std::is_arithmetic>') to type 'std::true_type {aka std::integral_constant<bool, true>}' 

जो कम से कम त्रुटि में ले जाता है (कि const char*नहीं है)।

+3

संकलक यह नहीं मानेंगे कि यह उस संदर्भ में एक मान है, क्योंकि यह एक मूल्य नहीं हो सकता है। तो बस 'is_arithmetic से विरासत में है :: टाइप' ठीक है। अनावश्यक, लेकिन ठीक है। – Barry

+0

@ बैरी मुझे संकलन के लिए सही नहीं करता है। विनोदी उपसर्ग हटा दिया। – Yakk

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