diff --git a/wrap/Class.cpp b/wrap/Class.cpp index 09433d616..6e415065d 100644 --- a/wrap/Class.cpp +++ b/wrap/Class.cpp @@ -319,11 +319,11 @@ void Class::addMethod(bool verbose, bool is_const, Str methodName, const ArgumentList& argumentList, const ReturnValue& returnValue, const Template& tmplate) { // Check if templated - if (!tmplate.argName.empty() && tmplate.argValues.size() > 0) { + if (tmplate.valid()) { // Create method to expand // For all values of the template argument, create a new method - BOOST_FOREACH(const Qualified& instName, tmplate.argValues) { - const TemplateSubstitution ts(tmplate.argName, instName, *this); + BOOST_FOREACH(const Qualified& instName, tmplate.argValues()) { + const TemplateSubstitution ts(tmplate.argName(), instName, *this); // substitute template in arguments ArgumentList expandedArgs = argumentList.expandTemplate(ts); // do the same for return type diff --git a/wrap/Module.cpp b/wrap/Module.cpp index decc390d6..917130f5c 100644 --- a/wrap/Module.cpp +++ b/wrap/Module.cpp @@ -200,7 +200,7 @@ void Module::parseMarkup(const std::string& data) { Rule class_p = eps_p[assign_a(cls,cls0)] >> (!(classTemplate_g - [push_back_a(cls.templateArgs, classTemplate.argName)] + [push_back_a(cls.templateArgs, classTemplate.argName())] | templateList_p) >> !(str_p("virtual")[assign_a(cls.isVirtual, true)]) >> str_p("class") @@ -216,7 +216,7 @@ void Module::parseMarkup(const std::string& data) { [assign_a(cls.namespaces_, namespaces)] [assign_a(cls.deconstructor.name,cls.name_)] [bl::bind(&handle_possible_template, bl::var(classes), bl::var(cls), - bl::var(classTemplate.argValues))] + bl::var(classTemplate.argValues()))] [clear_a(classTemplate)] [assign_a(constructor, constructor0)] [assign_a(cls,cls0)]; diff --git a/wrap/Template.h b/wrap/Template.h index cfa0db008..5a64412ed 100644 --- a/wrap/Template.h +++ b/wrap/Template.h @@ -23,13 +23,34 @@ namespace wrap { /// The template specification that goes before a method or a class -struct Template { - std::string argName; - std::vector argValues; - void clear() { - argName.clear(); - argValues.clear(); +class Template { + std::string argName_; + std::vector argValues_; + friend struct TemplateGrammar; +public: + /// The only way to get values into a Template is via our friendly Grammar + Template() { } + void clear() { + argName_.clear(); + argValues_.clear(); + } + const std::string& argName() const { + return argName_; + } + const std::vector& argValues() const { + return argValues_; + } + size_t nrValues() const { + return argValues_.size(); + } + const Qualified& operator[](size_t i) const { + return argValues_[i]; + } + bool valid() const { + return !argName_.empty() && argValues_.size() > 0; + } + }; /* ************************************************************************* */ @@ -41,7 +62,7 @@ struct TemplateGrammar: public classic::grammar { /// Construct type grammar and specify where result is placed TemplateGrammar(Template& result) : - result_(result), argValues_g(result.argValues) { + result_(result), argValues_g(result.argValues_) { } /// Definition of type grammar @@ -51,9 +72,10 @@ struct TemplateGrammar: public classic::grammar { classic::rule templateArgValues_p; definition(TemplateGrammar const& self) { - using namespace classic; + using classic::str_p; + using classic::assign_a; templateArgValues_p = (str_p("template") >> '<' - >> (BasicRules::name_p)[assign_a(self.result_.argName)] + >> (BasicRules::name_p)[assign_a(self.result_.argName_)] >> '=' >> self.argValues_g >> '>'); } @@ -65,5 +87,16 @@ struct TemplateGrammar: public classic::grammar { }; // TemplateGrammar -}// \namespace wrap +/// Cool initializer for tests +static inline boost::optional