2013-06-30 8 views
13

मैं इस तरह static_assert कैसे कर सकता हूं? हो सकता है कि बूस्ट इसका समर्थन करता है यदि सी ++ या सी ++ 11 में नई विशेषताएं नहीं हैं?एक static_assert करना कि एक टेम्पलेट प्रकार एक और टेम्पलेट है

template<T> 
struct foo {}; 

template<FooType> 
struct bar { 
    static_assert(FooType is indeed foo<T> for some T,"failure"); //how? 
}; 
+0

इससे संबंधित एक सवाल पाया जा सकता है [यहां] (http: // stackoverflow।कॉम/प्रश्न/12 9 1 9 310/सी-डिटेक्ट-टेम्पलेटेड-क्लास/12 9 1 9 3 9 6) –

उत्तर

23

आप इन पंक्तियों के साथ कुछ कर सकते हैं।

#include <type_traits> 

template<typename T, template<typename> class TT> 
struct is_instantiation_of : std::false_type { }; 

template<typename T, template<typename> class TT> 
struct is_instantiation_of<TT<T>, TT> : std::true_type { }; 

इसका इस्तेमाल अपने कार्यक्रम में इस प्रकार है::

template<typename T> 
struct foo {}; 

template<typename FooType> 
struct bar { 
    static_assert(is_instantiation_of<FooType, foo>::value, "failure"); 
}; 

int main() 
{ 
    bar<int> b; // ERROR! 
    bar<foo<int>> b; // OK! 
} 

आप चाहते हैं, तो आप इस सामान्यीकरण कर सकता था कि पता लगाने के लिए एक विशेषता एक वर्ग एक वर्ग टेम्पलेट का एक इन्स्टेन्शियशन है कि क्या सत्यापित कर सकते हैं कि यह देखते हुए एक वर्ग है, (प्रकार) मानकों के किसी भी संख्या के साथ एक टेम्पलेट का एक उदाहरण है इसलिए की तरह:

#include <type_traits> 

template<template<typename...> class TT, typename T> 
struct is_instantiation_of : std::false_type { }; 

template<template<typename...> class TT, typename... Ts> 
struct is_instantiation_of<TT, TT<Ts...>> : std::true_type { }; 

template<typename FooType> 
struct bar { 
    static_assert(is_instantiation_of<foo, FooType>::value, "failure"); 
}; 

फिर आप इसे अपने कार्यक्रम में इस तरह का प्रयोग करेंगे:

+०१२३५१६४१०६१
template<typename FooType> 
struct bar { 
    static_assert(is_instantiation_of<foo, FooType>::value, "failure"); 
}; 

int main() 
{ 
    bar<int> b; // ERROR! 
    bar<foo<int>> b; // OK! 
} 

यहां live example है।

+0

क्या आप (या यहां अन्य लोग) सोचते हैं कि पुस्तक "सी ++ टेम्पलेट्स: द पूर्ण गाइड" पुस्तक पढ़ने से ज्ञान वंदेवोर्डे और जोसुटिस ने मुझे करने की अनुमति दी होगी यह मेरे अपने पर है? –

+0

हम्म, शायद नहीं, चूंकि 'std :: true_type' एक सी ++ 11 सुविधा है :(सी ++ 11 के लिए कोई नई टेम्पलेट पुस्तकें प्रतीत नहीं होती हैं। –

+1

@ roger.james: यह एक अच्छा है पुस्तक और मैं इसे किसी भी तरह से पढ़ने की सलाह देता हूं। हालांकि, जैसा कि आपने बताया है, इस जवाब में मैंने सी ++ 11 विशेषताओं का उपयोग किया जो उस पुस्तक (विशेष रूप से विविध टेम्पलेट्स) में प्रस्तुत नहीं किए गए हैं। –

1

किसी और के रूप में लिखा था,

template<typename T, template<typename...> class TT> 
struct is_specialization_of : std::false_type { }; 

template<template<typename...> class TT, typename... Ts> 
struct is_specialization_of<TT<Ts...>, TT> : std::true_type { }; 

हालांकि, सावधान रहना है कि इस टेम्पलेट वर्गों जिसका टेम्प्लेट पैरामीटर सभी typenames हैं के लिए ही काम करता है!

typedef std::array<int, 42> MyArray; 
static_assert(is_specialization_of<MyArray, std::array>::value, ""); 

साथ प्रस्तुत यह बस सब पर संकलित करने के लिए असफल हो जायेगी।

मुझे विश्वास है कि सी ++ 11/सी ++ 14/सी ++ 17 वर्तमान में इस सीमा से निपटने का कोई तरीका नहीं है।

+0

यह जवाब नहीं है किसी और के जवाब की प्रतिलिपि बनाना/चिपकाना और फिर उस पर टिप्पणी करना उचित उत्तर नहीं है। अगर आपके किसी के उत्तर पर कोई टिप्पणी है, तो उनके उत्तर पर एक टिप्पणी छोड़ दें। – xaxxon

+0

"कोई और" कौन है? कृपया इस उत्तर को उचित [एट्रिब्यूशन] (https://stackoverflow.blog/2009/06/25/attribution-required/) प्रदान करने के लिए अपडेट करें, जिसे आपने इस कोड की प्रतिलिपि बनाई है। क्या यह [ज़ीओ का जवाब यहां] [https://stackoverflow.com/a/12919396), या कोई अन्य जवाब था? –

+0

2017 में आपका स्वागत है, आप दो! :) अगर आपको ऐसा लगता है तो "एंडी प्रोल" को "किसी और को" संपादित करने के लिए स्वतंत्र महसूस करें। – Quuxplusone

0

अन्य उत्तर से अधिक कुछ छोटे सुधार:

  • नाम वास्तव में मानकों
  • std :: क्षय
  • औजार के माध्यम से ठीक से हैंडल const, volatile, और संदर्भ प्रकार के आदेश के बारे में समझ में आता है सी ++ 14-शैली _v constexpr परिवर्तनीय
  • परीक्षण के लिए मनमाने ढंग से प्रकारों को स्वीकार करता है (सभी के लिए परीक्षण)

मैंने जानबूझकर std :: decay_t को is_template_for_v पर नहीं रखा है क्योंकि एक प्रकार की विशेषता को समान रूप से काम करना चाहिए चाहे उसे _v प्रत्यय या नहीं कहा जाता है या नहीं।

यह std::conjunction के लिए सी ++ 17 की आवश्यकता होती है, लेकिन आप या तो variadic सुविधा हटाने या अपने खुद के conjunction का उपयोग कर C++ 11/14 को लागू कर सकते हैं।

template<template<class...> class tmpl, typename T> 
struct _is_template_for : public std::false_type {}; 

template<template<class...> class tmpl, class... Args> 
struct _is_template_for<tmpl, tmpl<Args...>> : public std::true_type {}; 

template<template<class...> class tmpl, typename... Ts> 
using is_template_for = std::conjunction<_is_template_for<tmpl, std::decay_t<Ts>>...>; 

template<template<class...> class tmpl, typename... Ts> 
constexpr bool is_template_for_v = is_template_for<tmpl, Ts...>::value; 

उपयोग:

static_assert(is_template_for_v<std::vector, std::vector<int>>); // doesn't fire 
संबंधित मुद्दे