I want to refactor a function interface that uses Boost_PP by using variadic templates. The interface allows to register function objects. In pseudo code this looks like this:
template<typename F,
typename ReturnValue, typname Arg1, ..., typename ArgN,
typename Example1, ..., typename ExampleN>
void registerFunction(F&& function,
std::string parameterName1, std::string parameterDescription1, Example1 e1, ....,
std::string parameterNameN, std::string parameterDescriptionN, ExampleN en);
float rectangleArea(const float width, const float heigth);
registerFunction<float, const float, const float>(&rectangleArea,
"width", "width of rectangle", 2,
"height", "height of parameter", 4);
I tried to replace the Boost_PP created function with:
template<typename F, typename ReturnValue, typname ... Args, typename ... Description>
void registerFunction(F&& function, Description&& ... desc);
However, every third element must be so that if forwarded to the function
the object is callable. Eg. in pseudo code:
function(std::forward<Description2>(desc2),std::forward<Description5>(desc5),.....)
I tried to use SFINAE to restrict my function to valid descriptions.
template<typename Args, typename Descriptions, typename Enable = void>
struct ParameterParser: std::false_type
{};
// recursion end
template<typename Enable>
struct ParameterParser<std::tuple<>, std::tuple<>, Enable>: std::true_type
{};
template<typename Argument, typename ... RemainingArguments, typename Name, typename ParameterDescription, typename Example, typename ... RemainingDescription>
struct ParameterParser<std::tuple<Argument, RemainingArguments...>,
std::tuple<Name, ParameterDescription, Example, RemainingDescription...>,
typename std::enable_if<
(sizeof...(RemainingArguments)) * 3 == sizeof...(RemainingDescription)
&& std::is_convertible<Example, Argument>::value
&& std::is_convertible<ParameterDescription, std::string>::value
&& std::is_convertible<Name, std::string>::value>::type>
:ParameterParser<std::tuple<RemainingArguments...>, std::tuple<RemainingDescription...>>
{};
template<typename ArgumentTuple, typename DescriptionTuple>
using ValidDescription = typename std::enable_if<ParameterParser<ArgumentTuple, DescriptionTuple>::value>::type;
template<typename ReturnValue, typename ... Args, typename ... Description, typename F,
typename = ValidDescription<std::tuple<Args...>, std::tuple<Description...>>>
void registerFunction(F&& function, Description&& ... desc)
{
}
However, it seems like std::is_convertible<Example, Argument>::value
is not the correct trait for my use case. The problem is the following:
void functionToRegister(int&);
// this won't compile
registerFunction<void, int&>(&functionToRegister, "a parameter", "a description", 1);
The 1
is deduced as int
and std::is_convertible<int, int&>::value
is false.
How can i express a condition between two types 'ARG' and 'CallOBJ' that says: the parameter a
of a function f(ARG a)
can be initialized with something of type CallOBJ
.
Note that i am limited to C++11 :(
Here is a godbold link to my problem: https://godbolt.org/z/PMGon1f8q
Aucun commentaire:
Enregistrer un commentaire