cppfront
cppfront copied to clipboard
declarations in metafunctions
New:
This merge request adds the new function 'add_declaration_to_parent_namespacein the
compiler_services`. This allows metafunctions to add declarations to the outer namespace of the current declaration.
One example of such a use case would be to create a make function:
//-----------------------------------------------------------------------
//
// maker - add a make_<class name> function
//
maker: (inout t: meta::type_declaration) =
{
t.add_declaration_to_parent_namespace("make_(t.name())$: (args...: _) -> _ = { return (t.name())$(args...); }");
}
The merge request depends on #506. One of the unique pointer declarations caused one of the corner cases in UFCS.
Old: I wanted to play around a little bit with my own metafunctions. For my application I need to declare something outside of the structure, that "calls" the metafunction.
Patch 5a04b1d020bb617880200109e942e2114b738274 adds this functionality and 3ea209bb8b08d690a86069c15ca4575d107bb0d6 provides an example implementation. It creates a make_<name>
function like the ones for make_tuple
.
I wanted to post this here so I can get some feedback on the implementation. It probably needs to be polished a little bit. One question would be if the member metafunction_declarations
is the right approach?
An example for my usecase is implemented in dfb1113f4ce045b62181fb7935e89ff3576c4943. What we do is to implement some operators and add them to an expression framework. In order to that, we need to overload the original operator for the expression types. E.g. you have double * double
and you want to have Expr * Expr
. The overloads are always the same and we currently create them with super macros. That is we have *.tpp
file which has no include guards and expects some preprocessor macros definitions. This could be:
#ifndef OPERATION_LOGIC
#error Please define a name for the binary expression.
#endif
#ifndef FUNCTION
#error Please define the primal function representation.
#endif
template<typename Real, typename ArgA, typename ArgB>
auto FUNCTION(
ExpressionInterface<Real, ArgA> const& argA, ExpressionInterface<Real, ArgB> const& argB) {
return BinaryExpression<Real, ArgA, ArgB, OPERATION_LOGIC>(argA, argB);
}
template<typename Real, typename ArgA>
auto FUNCTION(
ExpressionInterface<Real, ArgA> const& argA, RealTraits::PassiveReal<Real> const& argB) {
return BinaryExpression<Real, ArgA, ConstantExpression<RealTraits::PassiveReal<Real>>, OPERATION_LOGIC>(
argA, ConstantExpression<RealTraits::PassiveReal<Real>>(argB));
}
template<typename Real, typename ArgB>
auto FUNCTION(
RealTraits::PassiveReal<Real> const& argA, ExpressionInterface<Real, ArgB> const& argB) {
return BinaryExpression<Real, ConstantExpression<RealTraits::PassiveReal<Real>>, ArgB, OPERATION_LOGIC>(
ConstantExpression<RealTraits::PassiveReal<Real>>(argA), argB);
}
#undef FUNCTION
#undef OPERATION_LOGIC
For functions with more than 2 arguments this can get quite large, since we need 2^n - 1
combinations with n
the number of arguments.
dfb1113f4ce045b62181fb7935e89ff3576c4943 also just adds the variants for the binary expression. But it would be quite simple to write a general generate_expressions
metafunction which creates the 2^n - 1
possibilities. One could even extend the functionality so that for certain arguments no expression version is generated or that the constant version is not generated.
Thanks for the comments. If there is nothing else, I would remove my examples and squash the commits.
Cleaned up the merge request and updated the first comment.
Removed WIP status.