2013-07-18 7 views
7

मैं निम्नलिखित (केवल प्रासंगिक कोड के नीचे भागों) करने के लिए कोशिश कर रहा हूँ:संकलन के दौरान एक constexpr स्ट्रिंग मुद्रित करने का कोई तरीका है?

template<typename ContainerType> 
struct IsContainerCheck : is_container<ContainerType> 
{ 
    static constexpr char* err_value = "Type is not a container model"; 
}; 

namespace _check_concept { 
    template<typename ResultType> 
    struct run { 
     constexpr static int apply() { 
      static_assert(false, IsContainerCheck<ResultType>::err_value) 
      return 0; 
     } 
    }; 

    template<> 
    struct run<true_t> { 
     constexpr static int apply() { 
      return 0; 
     } 
    }; 
} 

यह विफल रहता है क्योंकि static_assert की अनुमति देता है केवल शाब्दिक मुद्रित करने के लिए। BOOST_STATIC_ASSERT_MSG मैक्रो के साथ भी यही है।

तो मेरा सवाल है - संकलन के दौरान एक constexpr स्ट्रिंग आउटपुट करने का कोई तरीका है? यदि कोई कार्यक्षमता प्रदान करने वाला कोई gcc एक्सटेंशन है जो भी बहुत अच्छा होगा।

प्रयुक्त संकलक जीसीसी 4.8.1

उत्तर

6

जीसीसी तरह के एक तंत्र प्रदान नहीं करता है के रूप में आप चाहते हैं। हालांकि आपको की आवश्यकता नहीं होगी यदि आप प्रोग्राम के बाद में चित्रित कुछ हद तक अपने कोड को दोबारा करने में सक्षम हैं। (मैं कुछ अंतराल में भरा है तो के रूप में हमें एक compilable उदाहरण देने के लिए):

#include <type_traits> 
#include <vector> 

template<typename ContainerType> 
struct is_container 
{ 
    static bool const value = false; 
}; 

template<> 
struct is_container<std::vector<int>> 
{ 
    static bool const value = true; 
}; 

template<typename ContainerType> 
struct IsContainerCheck // : is_container<ContainerType> <- Uneccessary 
{ 
    static_assert(is_container<ContainerType>::value, 
     "Type is not a container model"); 
}; 

namespace _check_concept { 
    template<typename ResultType> 
    struct run { 
     constexpr static int apply() { 
      return (IsContainerCheck<ResultType>(),0); 
     } 
    }; 

    // No such specialization is necessary. Delete it. 
    // template<> 
    // struct run<true_t> { 
    // constexpr static int apply() { 
    //  return 0; 
    // } 
    //}; 
} 

using namespace _check_concept; 

int main(int argc, char **argv) 
{ 
    auto verdict0 = run<std::vector<int>>::apply(); 
    (void)verdict0; 
    // The following line will static_assert: "Type is not a container model" 
    auto verdict1 = run<float>::apply(); 
    (void)verdict1; 
    return 0; 
} 

अपने विशेषज्ञता में _check_concept::struct run<true_t> मुझे लगता है कि true_tनहीं एक उपनाम या std::true_type के बराबर है, बल्कि सिर्फ के लिए एक स्थान धारक कुछ ResultType जो एक कंटेनर प्रकार है। परीक्षण कार्यक्रम के रूप में पता चलता है, ऐसी कोई विशेषज्ञता, अब आवश्यक है, क्योंकि IsContainerCheck<ResultType>()static_assert, या नहीं होगा, ResultType पर निर्भर करता है, unspecialized run<ResultType>::apply() में।

+0

मुझे उम्मीद है कि जैसे ही टेम्पलेट तत्काल हो, चेक की आवश्यकता होगी, जिसके लिए जरूरी नहीं है कि किसी ऑब्जेक्ट का निर्माण किया जाए। – aschepler

+0

काफी। कोशिश करने और व्यक्त करने के लिए बस संपादित किया गया। –

+0

मैं बस उस पैरा को खरोंच कर दूंगा।मैंने सोचा कि मेरे पास एक गोचा था जिसने रैपर पर एक कन्स्ट्रक्टर कॉल की आवश्यकता थी, लेकिन मैं इसे आसान नहीं बना सकता, इसलिए यह मेरे कोड के साथ कुछ गलत है। –

0

समस्या के बारे में और सोचने के लिए मेरे पास कुछ समय था (और इसके साथ आने के लिए एक अच्छा शराब)।

namespace _details { 
    struct PassedCheck { 
    constexpr static int printError() { 
     return 0; //no error concept check passed 
    } 
    }; 

    template<template<typename> class ConceptCheck, typename ...ModelTypes> 
    struct check_concept_impl; 

    template<template<typename> class ConceptCheck, typename FirstType, typename ...ModelTypes> 
    struct check_concept_impl<ConceptCheck, FirstType, ModelTypes...> : mpl::eval_if< typename ConceptCheck<FirstType>::type, 
                    check_concept_impl<ConceptCheck, ModelTypes...>, 
                    mpl::identity<ConceptCheck<FirstType>>> 
    { }; 

    template<template<typename> class ConceptCheck, typename LastType> 
    struct check_concept_impl<ConceptCheck, LastType> : mpl::eval_if<typename ConceptCheck<LastType>::type, 
                   mpl::identity<PassedCheck>, 
                   mpl::identity<ConceptCheck<LastType>>> 
    { }; 


} 

template<template<typename> class ConceptCheck, typename ...ModelTypes> 
struct check_concept { 
private: 
    typedef typename _details::check_concept_impl<ConceptCheck, ModelTypes...>::type  result_type; 

public: 
// the constexpr method assert produces shorter, fixed depth (2) error messages than a nesting assert in the trait solution 
// the error message is not trahsed with the stack of variadic template recursion 
    constexpr static int apply() { 
    return result_type::printError(); 
    } 
}; 


template<typename ContainerType> 
struct IsContainerCheck : is_container<ContainerType> 
{ 
    template<typename BoolType = false_t> 
    constexpr static int printError() { 
     static_assert(BoolType::value, "Type is not a container model"); 
     return 0; 
    } 
}; 

और उपयोग:

check_concept<IsContainerCheck, std::vector<int>, std::vector<int>, float, int>::apply(); 

समाधान शायद सबसे सुंदर एक नहीं है लेकिन मैं इसे ज़ोर संदेश छोटा रहता है:

In file included from ../main.cpp:4:0: ../constraint.check.hpp: In instantiation of ‘static constexpr int IsContainerCheck::printError() [with BoolType = std::integral_constant; ContainerType = float]’: ../constraint.check.hpp:61:34: required from ‘static constexpr int check_concept::apply() [with ConceptCheck = IsContainerCheck; ModelTypes = {std::vector >, std::vector >, float, int}]’ ../main.cpp:25:83: required from here ../constraint.check.hpp:74:3: error: static assertion failed: Type is not a container model static_assert(BoolType::value, "Type is not a container model");

यह है कि मैं क्या लेकर आए हैं

चेक_कॉन्सेप्ट टेम्पलेट विशेषज्ञता के बाद एक कॉन्स्टेक्स विधि में जोर दिया जाता है। टेम्पलेट क्लास परिभाषा में सीधे स्थिर आवेषण को एम्बेड करने से त्रुटि संदेश में संपूर्ण check_concept_impl रिकर्सन स्टैक खींच जाएगा।

तो (readibility के लिए छोड़े गए परिवर्तनों के बाकी) की तरह कुछ करने के लिए IsContainerCheck विशेषता को बदलने:

template<typename ContainerType> 
struct IsContainerCheck 
{ 
static_assert(is_container<ContainerType>::type::value, "Type is not a container model"); 
}; 

एक त्रुटि

../constraint.check.hpp: In instantiation of ‘struct IsContainerCheck’: ../constraint.check.hpp:36:9: required from ‘struct _details::check_concept_impl’ /usr/include/boost/mpl/eval_if.hpp:38:31: required from ‘struct boost::mpl::eval_if, _details::check_concept_impl, boost::mpl::identity > > >’ ../constraint.check.hpp:36:9: required from ‘struct _details::check_concept_impl >, float, int>’ /usr/include/boost/mpl/eval_if.hpp:38:31: required from ‘struct boost::mpl::eval_if, _details::check_concept_impl >, float, int>, boost::mpl::identity > > >’ ../constraint.check.hpp:36:9: required from ‘struct _details::check_concept_impl >, std::vector >, float, int>’ ../constraint.check.hpp:53:84: required from ‘struct check_concept >, std::vector >, float, int>’ ../main.cpp:25:81: required from here ../constraint.check.hpp:72:2: error: static assertion failed: Type is not a container model static_assert(is_container::type::value, "Type is not a container model");

उपज आप देख सकते हैं प्रत्येक पुनरावर्ती eval_if कॉल emended है होगा त्रुटि विवरण में जो खराब है क्योंकि यह त्रुटि संदेश और टेम्पलेट पैरामीटर के प्रकार से निर्भर त्रुटि संदेश बनाता है।

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

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