Can define template classes in wrap interface file with a fixed list of template argument expansions, to quickly generate many classes, e.g. template<T = {gtsam::Point2,gtsam::Point3}> class BetweenFactor ... generates gtsamBetweenFactorPoint2, gtsamBetweenFactorPoint3, etc.
parent
42dec286ee
commit
c4f19a2b96
|
@ -211,3 +211,90 @@ void Class::pointer_constructor_fragments(FileWriter& proxyFile, FileWriter& wra
|
|||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
vector<ArgumentList> expandArgumentListsTemplate(const vector<ArgumentList>& argLists, const string& templateArg, const vector<string>& instName) {
|
||||
vector<ArgumentList> result;
|
||||
BOOST_FOREACH(const ArgumentList& argList, argLists) {
|
||||
ArgumentList instArgList;
|
||||
BOOST_FOREACH(const Argument& arg, argList) {
|
||||
Argument instArg = arg;
|
||||
if(arg.type == templateArg) {
|
||||
instArg.namespaces.assign(instName.begin(), instName.end()-1);
|
||||
instArg.type = instName.back();
|
||||
}
|
||||
instArgList.push_back(instArg);
|
||||
}
|
||||
result.push_back(instArgList);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
template<class METHOD>
|
||||
map<string, METHOD> expandMethodTemplate(const map<string, METHOD>& methods, const string& templateArg, const vector<string>& instName) {
|
||||
map<string, METHOD> result;
|
||||
typedef pair<const string, METHOD> Name_Method;
|
||||
BOOST_FOREACH(const Name_Method& name_method, methods) {
|
||||
const METHOD& method = name_method.second;
|
||||
METHOD instMethod = method;
|
||||
instMethod.argLists = expandArgumentListsTemplate(method.argLists, templateArg, instName);
|
||||
instMethod.returnVals.clear();
|
||||
BOOST_FOREACH(const ReturnValue& retVal, method.returnVals) {
|
||||
ReturnValue instRetVal = retVal;
|
||||
if(retVal.type1 == templateArg) {
|
||||
instRetVal.namespaces1.assign(instName.begin(), instName.end()-1);
|
||||
instRetVal.type1 = instName.back();
|
||||
}
|
||||
if(retVal.type2 == templateArg) {
|
||||
instRetVal.namespaces2.assign(instName.begin(), instName.end()-1);
|
||||
instRetVal.type2 = instName.back();
|
||||
}
|
||||
}
|
||||
result.insert(make_pair(name_method.first, instMethod));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
vector<Class> Class::expandTemplate(const string& templateArg, const vector<vector<string> >& instantiations) const {
|
||||
vector<Class> result;
|
||||
BOOST_FOREACH(const vector<string>& instName, instantiations) {
|
||||
Class inst;
|
||||
inst.name = name + instName.back();
|
||||
inst.typedefName = qualifiedName("::") + "<" + wrap::qualifiedName("::", instName) + ">";
|
||||
inst.isVirtual = isVirtual;
|
||||
inst.qualifiedParent = qualifiedParent;
|
||||
inst.methods = expandMethodTemplate(methods, templateArg, instName);
|
||||
inst.static_methods = expandMethodTemplate(static_methods, templateArg, instName);
|
||||
inst.namespaces = namespaces;
|
||||
inst.using_namespaces = using_namespaces;
|
||||
bool allIncludesEmpty = true;
|
||||
BOOST_FOREACH(const string& inc, includes) { if(!inc.empty()) { allIncludesEmpty = true; break; } }
|
||||
if(allIncludesEmpty)
|
||||
inst.includes.push_back(name + ".h");
|
||||
else
|
||||
inst.includes = includes;
|
||||
inst.constructor = constructor;
|
||||
inst.constructor.args_list = expandArgumentListsTemplate(constructor.args_list, templateArg, instName);
|
||||
inst.constructor.name = inst.name;
|
||||
inst.deconstructor = deconstructor;
|
||||
inst.deconstructor.name = inst.name;
|
||||
inst.verbose_ = verbose_;
|
||||
result.push_back(inst);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
std::string Class::getTypedef() const {
|
||||
string result;
|
||||
BOOST_FOREACH(const string& namesp, namespaces) {
|
||||
result += ("namespace " + namesp + " { ");
|
||||
}
|
||||
result += ("typedef " + typedefName + " " + name + ";");
|
||||
BOOST_FOREACH(const string& namesp, namespaces) {
|
||||
result += " }";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
|
|
|
@ -38,6 +38,7 @@ struct Class {
|
|||
|
||||
// Then the instance variables are set directly by the Module constructor
|
||||
std::string name; ///< Class name
|
||||
std::string typedefName; ///< The name to typedef *from*, if this class is actually a typedef, i.e. typedef [typedefName] [name]
|
||||
bool isVirtual; ///< Whether the class is part of a virtual inheritance chain
|
||||
std::vector<std::string> qualifiedParent; ///< The *single* parent - the last string is the parent class name, preceededing elements are a namespace stack
|
||||
Methods methods; ///< Class methods
|
||||
|
@ -54,6 +55,11 @@ struct Class {
|
|||
FileWriter& wrapperFile, std::vector<std::string>& functionNames) const; ///< emit proxy class
|
||||
std::string qualifiedName(const std::string& delim = "") const; ///< creates a namespace-qualified name, optional delimiter
|
||||
|
||||
std::vector<Class> expandTemplate(const std::string& templateArg, const std::vector<std::vector<std::string> >& instantiations) const;
|
||||
|
||||
// The typedef line for this class, if this class is a typedef, otherwise returns an empty string.
|
||||
std::string getTypedef() const;
|
||||
|
||||
private:
|
||||
void pointer_constructor_fragments(FileWriter& proxyFile, FileWriter& wrapperFile, const std::string& wrapperName, std::vector<std::string>& functionNames) const;
|
||||
};
|
||||
|
|
|
@ -51,6 +51,19 @@ typedef rule<BOOST_SPIRIT_CLASSIC_NS::phrase_scanner_t> Rule;
|
|||
// and with start rule [class_p], doubles as the specs for our interface files.
|
||||
/* ************************************************************************* */
|
||||
|
||||
/* ************************************************************************* */
|
||||
void handle_possible_template(vector<Class>& classes, const Class& cls, const string& templateArgument, const vector<vector<string> >& instantiations) {
|
||||
if(instantiations.empty()) {
|
||||
classes.push_back(cls);
|
||||
} else {
|
||||
vector<Class>& classInstantiations = cls.expandTemplate(templateArgument, instantiations);
|
||||
BOOST_FOREACH(const Class& c, classInstantiations) {
|
||||
classes.push_back(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
Module::Module(const string& interfacePath,
|
||||
const string& moduleName, bool enable_verbose) : name(moduleName), verbose(enable_verbose)
|
||||
{
|
||||
|
@ -72,6 +85,9 @@ Module::Module(const string& interfacePath,
|
|||
namespace_includes, /// current set of includes
|
||||
namespaces_return, /// namespace for current return type
|
||||
using_namespace_current; /// All namespaces from "using" declarations
|
||||
string templateArgument;
|
||||
vector<string> templateInstantiationNamespace;
|
||||
vector<vector<string> > templateInstantiations;
|
||||
string include_path = "";
|
||||
const string null_str = "";
|
||||
|
||||
|
@ -116,11 +132,23 @@ Module::Module(const string& interfacePath,
|
|||
className_p[assign_a(arg.type)] >>
|
||||
(ch_p('*')[assign_a(arg.is_ptr,true)] | ch_p('&')[assign_a(arg.is_ref,true)]);
|
||||
|
||||
Rule name_p = lexeme_d[alpha_p >> *(alnum_p | '_')];
|
||||
|
||||
Rule classParent_p =
|
||||
*(namespace_name_p[push_back_a(cls.qualifiedParent)] >> str_p("::")) >>
|
||||
className_p[push_back_a(cls.qualifiedParent)];
|
||||
|
||||
Rule name_p = lexeme_d[alpha_p >> *(alnum_p | '_')];
|
||||
Rule templateInstantiation_p =
|
||||
(*(namespace_name_p[push_back_a(templateInstantiationNamespace)] >> str_p("::")) >>
|
||||
className_p[push_back_a(templateInstantiationNamespace)])
|
||||
[push_back_a(templateInstantiations, templateInstantiationNamespace)]
|
||||
[clear_a(templateInstantiationNamespace)];
|
||||
|
||||
Rule templateInstantiations_p =
|
||||
str_p("template") >>
|
||||
'<' >> name_p[assign_a(templateArgument)] >> '=' >> '{' >>
|
||||
!(templateInstantiation_p >> *(',' >> templateInstantiation_p)) >>
|
||||
'}' >> '>';
|
||||
|
||||
Rule argument_p =
|
||||
((basisType_p[assign_a(arg.type)] | argEigenType_p | eigenRef_p | classArg_p)
|
||||
|
@ -202,10 +230,11 @@ Module::Module(const string& interfacePath,
|
|||
|
||||
Rule class_p =
|
||||
(!*include_p
|
||||
>> !(templateInstantiations_p)
|
||||
>> !(str_p("virtual")[assign_a(cls.isVirtual, true)])
|
||||
>> str_p("class")[push_back_a(cls.includes, include_path)][assign_a(include_path, null_str)]
|
||||
>> className_p[assign_a(cls.name)]
|
||||
>> ((':' >> classParent_p >> '{') | '{') // By having (parent >> '{' | '{') here instead of (!parent >> '{'), we trigger a parse error on a badly-formed parent spec
|
||||
>> ((':' >> classParent_p >> '{') | '{')
|
||||
>> *(functions_p | comments_p)
|
||||
>> str_p("};"))
|
||||
[assign_a(constructor.name, cls.name)]
|
||||
|
@ -215,10 +244,12 @@ Module::Module(const string& interfacePath,
|
|||
[append_a(cls.includes, namespace_includes)]
|
||||
[assign_a(deconstructor.name,cls.name)]
|
||||
[assign_a(cls.deconstructor, deconstructor)]
|
||||
[push_back_a(classes, cls)]
|
||||
[assign_a(deconstructor,deconstructor0)]
|
||||
[assign_a(constructor, constructor0)]
|
||||
[assign_a(cls,cls0)];
|
||||
[bl::bind(&handle_possible_template, bl::var(classes), bl::var(cls), bl::var(templateArgument), bl::var(templateInstantiations))]
|
||||
[assign_a(deconstructor,deconstructor0)]
|
||||
[assign_a(constructor, constructor0)]
|
||||
[assign_a(cls,cls0)]
|
||||
[clear_a(templateArgument)]
|
||||
[clear_a(templateInstantiations)];
|
||||
|
||||
Rule namespace_def_p =
|
||||
(!*include_p
|
||||
|
@ -413,6 +444,13 @@ void Module::matlab_code(const string& toolboxPath, const string& headerPath) co
|
|||
// Generate includes while avoiding redundant includes
|
||||
generateIncludes(wrapperFile);
|
||||
|
||||
// create typedef classes
|
||||
BOOST_FOREACH(const Class& cls, classes) {
|
||||
if(!cls.typedefName.empty())
|
||||
wrapperFile.oss << cls.getTypedef() << "\n";
|
||||
}
|
||||
wrapperFile.oss << "\n";
|
||||
|
||||
// Generate all collectors
|
||||
BOOST_FOREACH(const Class& cls, classes) {
|
||||
const string matlabName = cls.qualifiedName(), cppName = cls.qualifiedName("::");
|
||||
|
|
Loading…
Reference in New Issue