Changes to wrap from FixedValues branch/PR. Since unrelated to that PR and useful for OptionalJacobian wrapping in py_wrap, made this a separate PR.
parent
5a94b71c5f
commit
699943d632
|
@ -28,6 +28,7 @@
|
|||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <iterator> // std::ostream_iterator
|
||||
//#include <cstdint> // on Linux GCC: fails with error regarding needing C++0x std flags
|
||||
//#include <cinttypes> // same failure as above
|
||||
|
@ -314,6 +315,25 @@ vector<Class> Class::expandTemplate(Str templateArg,
|
|||
return result;
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
vector<Class> Class::expandTemplate(Str templateArg,
|
||||
const vector<int>& integers) const {
|
||||
vector<Class> result;
|
||||
BOOST_FOREACH(int i, integers) {
|
||||
Qualified expandedClass = (Qualified) (*this);
|
||||
stringstream ss; ss << i;
|
||||
string instName = ss.str();
|
||||
expandedClass.expand(instName);
|
||||
const TemplateSubstitution ts(templateArg, instName, expandedClass);
|
||||
Class inst = expandTemplate(ts);
|
||||
inst.name_ = expandedClass.name();
|
||||
inst.templateArgs.clear();
|
||||
inst.typedefName = qualifiedName("::") + "<" + instName + ">";
|
||||
result.push_back(inst);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
void Class::addMethod(bool verbose, bool is_const, Str methodName,
|
||||
const ArgumentList& argumentList, const ReturnValue& returnValue,
|
||||
|
|
|
@ -106,6 +106,10 @@ public:
|
|||
std::vector<Class> expandTemplate(Str templateArg,
|
||||
const std::vector<Qualified>& instantiations) const;
|
||||
|
||||
// Create new classes with integer template arguments
|
||||
std::vector<Class> expandTemplate(Str templateArg,
|
||||
const std::vector<int>& integers) const;
|
||||
|
||||
/// Add potentially overloaded, potentially templated method
|
||||
void addMethod(bool verbose, bool is_const, Str methodName,
|
||||
const ArgumentList& argumentList, const ReturnValue& returnValue,
|
||||
|
|
|
@ -47,15 +47,17 @@ namespace fs = boost::filesystem;
|
|||
// If a number of template arguments were given, generate a number of expanded
|
||||
// class names, e.g., PriorFactor -> PriorFactorPose2, and add those classes
|
||||
static void handle_possible_template(vector<Class>& classes, const Class& cls,
|
||||
const vector<Qualified>& instantiations) {
|
||||
if (cls.templateArgs.empty() || instantiations.empty()) {
|
||||
const Template& t) {
|
||||
if (cls.templateArgs.empty() || t.empty()) {
|
||||
classes.push_back(cls);
|
||||
} else {
|
||||
if (cls.templateArgs.size() != 1)
|
||||
throw std::runtime_error(
|
||||
"In-line template instantiations only handle a single template argument");
|
||||
vector<Class> classInstantiations = //
|
||||
cls.expandTemplate(cls.templateArgs.front(), instantiations);
|
||||
string arg = cls.templateArgs.front();
|
||||
vector<Class> classInstantiations =
|
||||
(t.nrValues() > 0) ? cls.expandTemplate(arg, t.argValues()) :
|
||||
cls.expandTemplate(arg, t.intList());
|
||||
BOOST_FOREACH(const Class& c, classInstantiations)
|
||||
classes.push_back(c);
|
||||
}
|
||||
|
@ -107,7 +109,7 @@ void Module::parseMarkup(const std::string& data) {
|
|||
Rule class_p = class_g //
|
||||
[assign_a(cls.namespaces_, namespaces)]
|
||||
[bl::bind(&handle_possible_template, bl::var(classes), bl::var(cls),
|
||||
bl::var(classTemplate.argValues()))]
|
||||
bl::var(classTemplate))]
|
||||
[clear_a(classTemplate)] //
|
||||
[assign_a(cls,cls0)];
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ namespace wrap {
|
|||
class Template {
|
||||
std::string argName_;
|
||||
std::vector<Qualified> argValues_;
|
||||
std::vector<int> intList_;
|
||||
friend struct TemplateGrammar;
|
||||
public:
|
||||
/// The only way to get values into a Template is via our friendly Grammar
|
||||
|
@ -34,13 +35,20 @@ public:
|
|||
void clear() {
|
||||
argName_.clear();
|
||||
argValues_.clear();
|
||||
intList_.clear();
|
||||
}
|
||||
const std::string& argName() const {
|
||||
return argName_;
|
||||
}
|
||||
const std::vector<int>& intList() const {
|
||||
return intList_;
|
||||
}
|
||||
const std::vector<Qualified>& argValues() const {
|
||||
return argValues_;
|
||||
}
|
||||
bool empty() const {
|
||||
return argValues_.empty() && intList_.empty();
|
||||
}
|
||||
size_t nrValues() const {
|
||||
return argValues_.size();
|
||||
}
|
||||
|
@ -53,16 +61,52 @@ public:
|
|||
|
||||
};
|
||||
|
||||
/* ************************************************************************* */
|
||||
// http://boost-spirit.com/distrib/spirit_1_8_2/libs/spirit/doc/grammar.html
|
||||
struct IntListGrammar: public classic::grammar<IntListGrammar > {
|
||||
|
||||
typedef std::vector<int> IntList;
|
||||
IntList& result_; ///< successful parse will be placed in here
|
||||
|
||||
/// Construct type grammar and specify where result is placed
|
||||
IntListGrammar(IntList& result) :
|
||||
result_(result) {
|
||||
}
|
||||
|
||||
/// Definition of type grammar
|
||||
template<typename ScannerT>
|
||||
struct definition {
|
||||
|
||||
classic::rule<ScannerT> integer_p, intList_p;
|
||||
|
||||
definition(IntListGrammar const& self) {
|
||||
using namespace classic;
|
||||
|
||||
integer_p = int_p[push_back_a(self.result_)];
|
||||
|
||||
intList_p = '{' >> !integer_p >> *(',' >> integer_p) >> '}';
|
||||
}
|
||||
|
||||
classic::rule<ScannerT> const& start() const {
|
||||
return intList_p;
|
||||
}
|
||||
|
||||
};
|
||||
};
|
||||
// IntListGrammar
|
||||
|
||||
/* ************************************************************************* */
|
||||
// http://boost-spirit.com/distrib/spirit_1_8_2/libs/spirit/doc/grammar.html
|
||||
struct TemplateGrammar: public classic::grammar<TemplateGrammar> {
|
||||
|
||||
Template& result_; ///< successful parse will be placed in here
|
||||
TypeListGrammar<'{', '}'> argValues_g; ///< TypeList parser
|
||||
IntListGrammar intList_g; ///< TypeList parser
|
||||
|
||||
/// Construct type grammar and specify where result is placed
|
||||
TemplateGrammar(Template& result) :
|
||||
result_(result), argValues_g(result.argValues_) {
|
||||
result_(result), argValues_g(result.argValues_), //
|
||||
intList_g(result.intList_) {
|
||||
}
|
||||
|
||||
/// Definition of type grammar
|
||||
|
@ -76,7 +120,7 @@ struct TemplateGrammar: public classic::grammar<TemplateGrammar> {
|
|||
using classic::assign_a;
|
||||
templateArgValues_p = (str_p("template") >> '<'
|
||||
>> (BasicRules<ScannerT>::name_p)[assign_a(self.result_.argName_)]
|
||||
>> '=' >> self.argValues_g >> '>');
|
||||
>> '=' >> (self.argValues_g | self.intList_g) >> '>');
|
||||
}
|
||||
|
||||
classic::rule<ScannerT> const& start() const {
|
||||
|
|
|
@ -127,6 +127,12 @@ class MyFactor {
|
|||
// and a typedef specializing it
|
||||
typedef MyFactor<gtsam::Pose2, Matrix> MyFactorPosePoint2;
|
||||
|
||||
// A class with integer template arguments
|
||||
template<N = {3,12}>
|
||||
class MyVector {
|
||||
MyVector();
|
||||
};
|
||||
|
||||
// comments at the end!
|
||||
|
||||
// even more comments at the end!
|
||||
|
|
|
@ -221,6 +221,29 @@ TEST( Class, TemplateSubstition ) {
|
|||
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
TEST( Class, TemplateSubstitionIntList ) {
|
||||
|
||||
using classic::space_p;
|
||||
|
||||
// Create type grammar that will place result in cls
|
||||
Class cls;
|
||||
Template t;
|
||||
ClassGrammar g(cls, t);
|
||||
|
||||
string markup(string("template<N = {3,4}>"
|
||||
"class Point2 {"
|
||||
" void myMethod(Matrix A) const;"
|
||||
"};"));
|
||||
|
||||
EXPECT(parse(markup.c_str(), g, space_p).full);
|
||||
|
||||
vector<Class> classes = cls.expandTemplate(t.argName(), t.intList());
|
||||
|
||||
// check the number of new classes is 2
|
||||
EXPECT_LONGS_EQUAL(2, classes.size());
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
TEST(Class, Template) {
|
||||
|
||||
|
|
|
@ -47,6 +47,15 @@ TEST( Template, grammar ) {
|
|||
EXPECT(actual[2]==Qualified("Vector",Qualified::EIGEN));
|
||||
EXPECT(actual[3]==Qualified("Matrix",Qualified::EIGEN));
|
||||
actual.clear();
|
||||
|
||||
EXPECT(parse("template<N = {1,2,3,4}>", g, space_p).full);
|
||||
EXPECT_LONGS_EQUAL(4, actual.intList().size());
|
||||
EXPECT(actual.argName()=="N");
|
||||
EXPECT_LONGS_EQUAL(1,actual.intList()[0]);
|
||||
EXPECT_LONGS_EQUAL(2,actual.intList()[1]);
|
||||
EXPECT_LONGS_EQUAL(3,actual.intList()[2]);
|
||||
EXPECT_LONGS_EQUAL(4,actual.intList()[3]);
|
||||
actual.clear();
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
|
|
|
@ -144,7 +144,7 @@ TEST( wrap, Small ) {
|
|||
TEST( wrap, Geometry ) {
|
||||
string markup_header_path = topdir + "/wrap/tests";
|
||||
Module module(markup_header_path.c_str(), "geometry",enable_verbose);
|
||||
EXPECT_LONGS_EQUAL(7, module.classes.size());
|
||||
EXPECT_LONGS_EQUAL(9, module.classes.size());
|
||||
|
||||
// forward declarations
|
||||
LONGS_EQUAL(2, module.forward_declarations.size());
|
||||
|
@ -155,7 +155,7 @@ TEST( wrap, Geometry ) {
|
|||
strvec exp_includes; exp_includes += "folder/path/to/Test.h";
|
||||
EXPECT(assert_equal(exp_includes, module.includes));
|
||||
|
||||
LONGS_EQUAL(7, module.classes.size());
|
||||
LONGS_EQUAL(9, module.classes.size());
|
||||
|
||||
// Key for ReturnType::return_category
|
||||
// CLASS = 1,
|
||||
|
|
Loading…
Reference in New Issue