Converting a variadic macro to a variadic template function? - variadic-functions

Given a variadic macro of the form:
#define MY_CALL_RETURN_F(FType, FId, ...) \
if(/*prelude omitted*/) { \
FType f = (FType)GetFuncFomId(FId); \
if(f) { \
return f(__VA_ARGS__); \
} else { \
throw invalid_function_id(FId); \
} \
} \
/**/
-- how can this be rewritten to a variadic function template?
template<typename FType, typename ...Args>
/*return type?*/ tmpl_call_return_f(MyFunId const& FId, /*what goes here?*/)
{
...
FType f = (FType)GetFuncFomId(FId);
return f(/*what goes here?*/);
...
}
Update: I'm specifically interested in how to declare the reference type for the Args: && or const& or what?
Update: Note that FType is supposed to be a "plain" function pointer.

It would look something like this:
template<typename FType, typename ...Args>
std::result_of<FType(Args...)>::type tmpl_call_return_f(MyFunId const& FId, Args... &&args)
{
FType f = (FType)GetFuncFomId(FId)
return f(std::forward<Args>(args)...);
}

If you use std::function as FType, then this should work:
template <typename FType, typename ...Args>
typename FType::result_type tmpl_call_return_f(MyFunId const& FId, Args... args) {
// ...
return f(args...);
}

Related

function template specialization for variadic templated function (printf)

I have some Arduino C++11 code that I'm trying to improve: trying to make a printf-like function treat String specially so I don't have to call c_str() myself everywhere I use it. Basically for any builtin type like int float bool etc, I just want to pass the arg as-is, and for String, pass return the c_str(). Hit some snags so I tried this in some of the online compilers available. Starting point is this, using std::string instead of String:
#include <string>
class SerialOut {
public:
template<class ...Ts>
static void error(const char* msg, Ts... args) {
printf(msg, args...);
}
};
int main() {
std::string greeting("hi");
SerialOut::error("Message %d %s\n", 1, greeting.c_str());
}
So I tried creating a function template that just returns the value it gets, with a specialization for std::string:
#include <string>
template <typename T, typename R=T> R raw(T& x) {return x;}
template <> const char* raw<>(std::string& x) {return x.c_str();}
class SerialOut {
public:
template<class ...Ts>
static void error(const char* msg, Ts... args) {
printf(msg, raw(args)...);
}
};
int main() {
std::string greeting("hi");
SerialOut::error("Message %d %s\n", 1, greeting);
}
I get a compilation error when I run this in https://repl.it/languages/cpp11:
clang version 7.0.0-3~ubuntu0.18.04.1 (tags/RELEASE_700/final)
 clang++-7 -pthread -std=c++11 -o main main.cpp
main.cpp:10:25: error: cannot pass object of non-trivial type
'std::__cxx11::basic_string<char>' through variadic function; call will abort at
runtime [-Wnon-pod-varargs]
printf(msg, raw(args)...);
^
main.cpp:16:20: note: in instantiation of function template specialization
'SerialOut::error<int, std::__cxx11::basic_string<char> >' requested here
SerialOut::error("Message %d %s\n", 1, greeting);
^
1 error generated.
compiler exit status 1
With https://www.onlinegdb.com/online_c++_compiler there is no error but the raw() specialization is not selected, so the output for greeting is garbage.
In Arduino IDE I get a slightly different error (after replacing std::string by String, of course):
sketch\mqtt.cpp.o: In function `char const* raw<String, char const*>(String&)':
sketch/utils.h:15: multiple definition of `char const* raw<String, char const*>(String&)'
sketch\Thermistor.cpp.o:sketch/utils.h:15: first defined here
sketch\sketch.ino.cpp.o: In function `char const* raw<String, char const*>(String&)':
sketch/utils.h:15: multiple definition of `char const* raw<String, char const*>(String&)'
sketch\Thermistor.cpp.o:sketch/utils.h:15: first defined here
I tried several variations on the raw() functions, to no avail. I figure I'm just missing a subtlety or it's just not possible to do this in C++11.
Update: I found Variadic Macro: cannot pass objects of non-trivially-copyable type through '...', one of the answers solves the above in C++14 (basically use decltype(auto) and overload instead of specialization). I added a slight variation on it that works also in C++11, and with "inline" it also works in Arduino C++ (without "inline" on the overload, the above message about multiple definitions -- turns out this is a linker message so it does compile, I guess the Arduino variant doesn't inline "obviously inlined" functions as other compilers).
Something along these lines, perhaps:
template <typename T>
struct SerialHelper {
static T raw(T val) { return val; }
};
template <>
struct SerialHelper<std::string> {
static const char* raw(const std::string& val) { return val.c_str(); }
};
class SerialOut {
public:
template<class ...Ts>
static void error(const char* msg, Ts... args) {
printf(msg, SerialHelper<Ts>::raw(args)...);
}
};
Demo
Based on Variadic Macro: cannot pass objects of non-trivially-copyable type through '...' I got it to work with this very simple change, which works in C++11 and Arduino C++:
#include <string>
template <typename T> T raw(const T& x) {return x;}
inline const char* raw(const String& x) {return x.c_str();}
class SerialOut {
public:
template<class ...Ts>
static void error(const char* msg, Ts... args) {
printf(msg, raw(args)...);
}
};
int main() {
std::string greeting("hi");
SerialOut::error("Message %d %s\n", 1, greeting);
}
Thanks to #IgorTandetnik comment, it is clear why.

Rcpp modules: Validator function for exposed constructors with same number of parameters

I would like to expose a C++ class with Rcpp modules that has two constructors with the same number of parameters. As documented in the Rcpp modules vignette, this can be achieved by using a validator function as the second argument to .constructor with the type
typedef bool (*ValidConstructor)(SEXP*,int);
Could somebody provide an example of how it is supposed to be used? In the vignette, there is only a TODO note that an example should be included there.
To follow up on nrussell's answer, you might want to generate the validators from templates, i.e.
template <typename T0, typename T1>
bool typed_valid( SEXP* args, int nargs ){
return nargs == 2 && Rcpp::is<T0>(args[0]) && Rcpp::is<T1>(args[1]) ;
}
which you would use as:
.constructor<int, int>( & typed_valid<int,int> )
obviously the typed_valid function template is straightforward to generalize with variadic templates.
With the disclaimer that I haven't personally used this before, the following appears to work:
#include <Rcpp.h>
using namespace Rcpp;
class Example {
public:
Example(int x_, int y_)
: x(x_), y(y_)
{
Rcout << __PRETTY_FUNCTION__ << "\n";
}
Example(std::string x_, std::string y_)
: x(x_.size()), y(y_.size())
{
Rcout << __PRETTY_FUNCTION__ << "\n";
}
int add() const
{ return x + y; }
private:
int x, y;
};
bool validate_int_int(SEXP* args, int nargs)
{ return TYPEOF(args[0]) == INTSXP && TYPEOF(args[1]) == INTSXP; }
bool validate_string_string(SEXP* args, int nargs)
{ return TYPEOF(args[0]) == STRSXP && TYPEOF(args[1]) == STRSXP; }
RCPP_MODULE(ExampleMod) {
class_<Example>("Example")
.constructor<int, int>(
"(int, int) constructor",
validate_int_int
)
.constructor<std::string, std::string>(
"(string, string) constructor",
validate_string_string
)
.method("add", &Example::add)
;
}
Testing from R,
ex.int <- new(Example, 1L, 2L)
# Example::Example(int, int)
ex.string <- new(Example, "one", "two")
# Example::Example(std::string, std::string)
ex.int$add()
# [1] 3
ex.string$add()
# [1] 6
In each of validate_int_int and validate_string_string we are just testing the input SEXP types against the signatures of their corresponding constructors.
Following the footsteps of previous answers, I found there is a chance that a universal validator function might exist by using variadic template in cpp.
The implementation is shorter than I have expected though there are many technical details beyond the scope of this post.
template <typename... Types>
bool universal_validator(SEXP* args, int nargs) {
return universal_validator<Types...>(args, nargs, 0);
}
template <typename T = void, typename... Types>
bool universal_validator(SEXP* args, int nargs, int idx) {
if (idx>=nargs) return false;
// optional type traits
typedef typename Rcpp::traits::remove_const_and_reference<T>::type _Tp;
return Rcpp::is<_Tp>(args[idx]) && universal_validator<Types...>(args, nargs, idx+1);
}
template <>
bool universal_validator<>(SEXP* args, int nargs, int idx) {
return nargs == idx;
}
The usage of this universal_validator is quite simple. Given the Example class, the constructors in the RCPP_MODULE will become as follows.
RCPP_MODULE(example_module) {
Rcpp::class_<Example>("Example")
.constructor<int, int>("(int, int) constructor",
universal_validator<int, int>)
.constructor<std::string, std::string> ("(string, string) constructor",
universal_validator<std::string, std::string>)
.method("add", &Example::add)
;
}
Just put the same argument types as the constructor in the validator template, e.g. universal_validator<int, int> will do the job. And this shall work as long as Rcpp::is<T> is defined for any type T.
The source code from github
SEXP newInstance( SEXP* args, int nargs ) indicates that the validator must check the types of SEXP* and nargs simultaneously. That's why not only the type but also the index of SEXP* is also checked in all functions.

VS2010 SFINAE and function overload error

I have code like this, that compiles fines in all compiler I've tested except VS2010.
I'm trying not to use C++11 specific features here, so it can still compile on outdated compiler like gcc 4.1.
#include <iostream>
using namespace std;
// Simplified variant class
struct Var
{
template <class T>
Var(T t) {}
Var(void) {}
};
// Simplified argument array class
struct FuncArgs
{
};
/** Make a wrapper around the given function */
template <int line, typename Ret, Ret Func()>
Var WrapFuncT(const FuncArgs & args)
{
Var ret;
ret = Func(); return ret;
}
/** Make a wrapper around the given function */
template <int line, void Func()>
Var WrapFuncT(const FuncArgs & args)
{
Var ret;
Func(); return ret;
}
// Unary
template <int line, typename Ret, typename Arg1, Ret Func(Arg1)>
Var WrapFuncT(const FuncArgs & args)
{
Var ret; Arg1 arg;
ret = Func(arg);
return ret;
}
template <int line, typename Arg1, void Func(Arg1)>
Var WrapFuncT(const FuncArgs & args)
{
Var ret; Arg1 arg;
Func(arg);
return ret;
}
// Binary
template <int line, typename Ret, typename Arg1, typename Arg2, Ret Func(Arg1, Arg2)>
Var WrapFuncT(const FuncArgs & args)
{
Var ret; Arg1 arg1; Arg2 arg2;
ret = Func(arg1, arg2);
return ret;
}
template <int line, typename Arg1, typename Arg2, void Func(Arg1, Arg2)>
Var WrapFuncT(const FuncArgs & args)
{
Var ret; Arg1 arg1; Arg2 arg2;
Func(arg1, arg2);
return ret;
}
#define WrapFunc(X, Y, ...) &WrapFuncT<__LINE__, X, Y, ## __VA_ARGS__ >
int testFunc()
{
return 42;
}
void testFunc2(int value)
{
cout<<value<<endl;
}
typedef Var (*NamedFunc)(const FuncArgs &);
int main()
{
NamedFunc a, b;
a = WrapFunc(int, testFunc);
b = WrapFunc(int, testFunc2);
}
Visual studio 2010 compiler chokes on this with error:
In line 'a = WrapFunc(int, testFunc);' : error C2440: 'specialization' : cannot convert from 'int (__cdecl *)(void)' to 'void (__cdecl *const )(int)'
This conversion requires a reinterpret_cast, a C-style cast or function-style cast
error C2973: 'Type::WrapFuncT' : invalid template argument 'int (__cdecl *)(void)'
In line 'template <int line, typename Arg1, void Func(Arg1)>' : see declaration of 'Type::WrapFuncT'
Seems like VS2010 does not find the former definition template < int line, typename Ret, Ret Func(void) > with Ret = int for int testFunc(void) function, and instead tries and errors on the template < int line, typename Arg1, void Func(Arg1) >.
If I comment the later, then it compiles fine, so it is able to find the former overload.
I've tried to solve this in numerous way, none worked, as I need to "capture" a pointer to function in a same signature function Var (*) (const FuncArgs &)
You may try a generic template function and using specialization with structure, something like:
namespace detail
{
// class to specialize for each function type
template <int line, typename F, F f> struct helper_wrapper;
// partial specialization
template <int line, typename Ret, Ret (&Func)()>
struct helper_wrapper<line, Ret (&)(void), Func>
{
Var operator()(const FuncArgs&) const
{
Var ret;
ret = Func();
return ret;
}
};
// partial specialization
template <int line, void (&Func)()>
struct helper_wrapper<line, void (&)(), Func>
{
Var operator()(const FuncArgs&) const
{
Var ret;
Func();
return ret;
}
};
// partial specialization
template <int line, typename Ret, typename Arg1, Ret (&Func)(Arg1)>
struct helper_wrapper<line, Ret (&)(Arg1), Func>
{
Var operator()(const FuncArgs&) const
{
Var ret;
Arg1 arg;
ret = Func(arg);
return ret;
}
};
// partial specialization
template <int line, typename Arg1, void (&Func)(Arg1)>
struct helper_wrapper<line, void (&)(Arg1), Func>
{
Var operator()(const FuncArgs&) const
{
Var ret;
Arg1 arg;
Func(arg);
return ret;
}
};
// other partial specialization omitted.
}
// The general function
template <int line, typename F, F f>
Var WrapFuncT(const FuncArgs& arg) { return detail::helper_wrapper<line, F, f>()(arg); }
// The helper macro
#define WrapFunc(X, Y) &WrapFuncT<__LINE__, X, Y>
And then call it that way:
a = WrapFunc(int(&)(), testFunc);
b = WrapFunc(void(&)(int), testFunc2);

Specialising templates on C++AMP restricted lambdas

Using the insight of this question (and a few others) I have been able to write the following for interrogating normal lambda function type infromation (i.e. return type, argument count etc)
// helper classes ========================================
template <typename R, typename... A>
class lambda_traits_evaluation {
public:
typedef R r_type;
enum { n_args = sizeof...(A) };
// ...
};
template <typename R, typename... A>
class lambda_traits_helper
: public lambda_traits_evaluation<R,A...>{};
template <typename R, typename F, typename... A>
class lambda_traits_helper<R (F::*)(A...) const>
: public lambda_traits_evaluation<R,A...>{};
// use class ========================================
template <typename F>
class lambda_traits {
typedef typename lambda_traits_helper<decltype(&F::operator())> helper_impl;
// ...
}
I can then use this with lambda_traits<decltype(myLambda)> but that is where my smug coding ends because if my lambda is amp restricted for the gpu i.e.
auto myLambda = [](int) restrict(amp) -> void {};
as obviously the template specialisation is not picked up. However adding the new specialisation
template <typename R, typename F, typename... A>
class lambda_traits_helper<R (F::*)(A...) const restrict(amp)>
: public lambda_traits_evaluation<R,A...> {};
still does not solve the problem as I discover that the compiler barks
error C3939: 'abstract declarator' : pointer to member functions, function
pointers, references to functions with 'amp' restriction
specifier are not allowed
is there another way to interrogate the types in lambdas or else a way to strip the restrict off the lambda type?
The inability to form a pointer to an amp-restricted function, even in unevaluated context, is a bummer. There is however a workaround, which is viable as long as you can require the amp-restricted lambdas to be cpu,amp-restricted. In such case you can cast-away the amp-restriction, forming a pointer to the cpu-restricted member function -- which you can interrogate further.
See the following proof-of-concept:
#include <type_traits>
template <typename R, typename F, typename... A>
auto get_R(R (F::*)(A...) const) -> R
{}
template <typename L>
struct lambda_traits
{
using ret_type = decltype(get_R(&L::operator()));
};
int main()
{
auto lambda_1 = [](int) restrict(cpu,amp) -> void {};
auto lambda_2 = [](int) restrict(cpu,amp) -> int { return 0; };
// Test:
static_assert(std::is_same<lambda_traits<decltype(lambda_1)>::ret_type, void>::value, "Failed 1.");
static_assert(std::is_same<lambda_traits<decltype(lambda_2)>::ret_type, int>::value, "Failed 2.");
}
Hope that helps!

C++ template : OKay for VC2005SP1, gcc bails out?

I'm puzzled here, and kindly request your help.
VC2005SP1 swallows this (stripped out) code but gcc 4.0.1 bails out... Please point me the obvious mistake ?
TIA!
template<typename BCT, typename UIDT>
class Factory
{
public:
template<typename CT>
bool Register(UIDT UniqueID)
{
if (UniqueID > 10)
return(false);
CreateObject2<BCT, CT>;
return(true);
}
};
template <typename MC, typename MT>
class Manager : public Factory<MC, MT>
{
public:
bool RegisterType(const MT Type, const std::string TypeName)
{
return Factory<MC, MT>::Register<MC>(Type); // gcc claims "expected primary-expression before '>' at this point
}
};
VS is being kind.
return Factory<MC, MT>::template Register<MC>(Type); should work under both compilers.

Resources