Template tightening

release/4.3a0
dellaert 2014-12-01 20:29:35 +01:00
parent de650069e2
commit aceeb2037b
5 changed files with 79 additions and 38 deletions

View File

@ -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

View File

@ -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)];

View File

@ -23,13 +23,34 @@
namespace wrap {
/// The template specification that goes before a method or a class
struct Template {
std::string argName;
std::vector<Qualified> argValues;
void clear() {
argName.clear();
argValues.clear();
class Template {
std::string argName_;
std::vector<Qualified> 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<Qualified>& 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<TemplateGrammar> {
/// 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<TemplateGrammar> {
classic::rule<ScannerT> templateArgValues_p;
definition(TemplateGrammar const& self) {
using namespace classic;
using classic::str_p;
using classic::assign_a;
templateArgValues_p = (str_p("template") >> '<'
>> (BasicRules<ScannerT>::name_p)[assign_a(self.result_.argName)]
>> (BasicRules<ScannerT>::name_p)[assign_a(self.result_.argName_)]
>> '=' >> self.argValues_g >> '>');
}
@ -65,5 +87,16 @@ struct TemplateGrammar: public classic::grammar<TemplateGrammar> {
};
// TemplateGrammar
}// \namespace wrap
/// Cool initializer for tests
static inline boost::optional<Template> CreateTemplate(const std::string& s) {
Template result;
TemplateGrammar g(result);
bool success = parse(s.c_str(), g, classic::space_p).full;
if (success)
return result;
else
return boost::none;
}
} // \namespace wrap

View File

@ -39,17 +39,14 @@ TEST( Class, OverloadingMethod ) {
bool verbose = true, is_const = true;
ArgumentList args;
const ReturnValue retVal;
const string templateArgName;
vector<Qualified> templateArgValues;
cls.addMethod(verbose, is_const, name, args, retVal, templateArgName,
templateArgValues);
const Template tmplate;
cls.addMethod(verbose, is_const, name, args, retVal, tmplate);
EXPECT_LONGS_EQUAL(1, cls.nrMethods());
EXPECT(cls.exists(name));
Method method = cls.method(name);
EXPECT_LONGS_EQUAL(1, method.nrOverloads());
cls.addMethod(verbose, is_const, name, args, retVal, templateArgName,
templateArgValues);
cls.addMethod(verbose, is_const, name, args, retVal, tmplate);
EXPECT_LONGS_EQUAL(1, cls.nrMethods());
EXPECT_LONGS_EQUAL(2, method.nrOverloads());
}
@ -67,12 +64,10 @@ TEST( Class, TemplatedMethods ) {
arg.type.name_ = "T";
args.push_back(arg);
const ReturnValue retVal(ReturnType("T"));
const string templateArgName("T");
vector<Qualified> templateArgValues;
templateArgValues.push_back(Qualified("Point2"));
templateArgValues.push_back(Qualified("Point3"));
cls.addMethod(verbose, is_const, name, args, retVal, templateArgName,
templateArgValues);
boost::optional<Template> tmplate = //
CreateTemplate("template<T = {Point2, Point3}>");
CHECK(tmplate);
cls.addMethod(verbose, is_const, name, args, retVal, *tmplate);
EXPECT_LONGS_EQUAL(2, cls.nrMethods());
EXPECT(cls.exists(name+"Point2"));
EXPECT(cls.exists(name+"Point3"));

View File

@ -32,22 +32,35 @@ TEST( Template, grammar ) {
TemplateGrammar g(actual);
EXPECT(parse("template<T = {gtsam::Point2, Matrix}>", g, space_p).full);
EXPECT_LONGS_EQUAL(2, actual.argValues.size());
EXPECT(actual.argName=="T");
EXPECT(actual.argValues[0]==Qualified("gtsam","Point2",Qualified::CLASS));
EXPECT(actual.argValues[1]==Qualified("Matrix",Qualified::EIGEN));
EXPECT_LONGS_EQUAL(2, actual.nrValues());
EXPECT(actual.argName()=="T");
EXPECT(actual[0]==Qualified("gtsam","Point2",Qualified::CLASS));
EXPECT(actual[1]==Qualified("Matrix",Qualified::EIGEN));
actual.clear();
EXPECT(parse("template<ARG = {gtsam::Point2, gtsam::Point3, Vector, Matrix}>", g, space_p).full);
EXPECT_LONGS_EQUAL(4, actual.argValues.size());
EXPECT(actual.argName=="ARG");
EXPECT(actual.argValues[0]==Qualified("gtsam","Point2",Qualified::CLASS));
EXPECT(actual.argValues[1]==Qualified("gtsam","Point3",Qualified::CLASS));
EXPECT(actual.argValues[2]==Qualified("Vector",Qualified::EIGEN));
EXPECT(actual.argValues[3]==Qualified("Matrix",Qualified::EIGEN));
EXPECT(
parse("template<ARG = {gtsam::Point2, gtsam::Point3, Vector, Matrix}>", g, space_p).full);
EXPECT_LONGS_EQUAL(4, actual.nrValues());
EXPECT(actual.argName()=="ARG");
EXPECT(actual[0]==Qualified("gtsam","Point2",Qualified::CLASS));
EXPECT(actual[1]==Qualified("gtsam","Point3",Qualified::CLASS));
EXPECT(actual[2]==Qualified("Vector",Qualified::EIGEN));
EXPECT(actual[3]==Qualified("Matrix",Qualified::EIGEN));
actual.clear();
}
//******************************************************************************
TEST( Template, CreateTemplate ) {
boost::optional<Template> actual = //
CreateTemplate("template<T = {gtsam::Point2, Matrix}>");
CHECK(actual);
// aborts if not true
EXPECT_LONGS_EQUAL(2, actual->nrValues());
EXPECT(actual->argName()=="T");
EXPECT((*actual)[0]==Qualified("gtsam","Point2",Qualified::CLASS));
EXPECT((*actual)[1]==Qualified("Matrix",Qualified::EIGEN));
}
//******************************************************************************
int main() {
TestResult tr;