Is &decltype(object)::memfn a misuse? - c++

I had some class like this:
class Test {
public:
bool bar(int &i, char c) // some arguments are passed by ref, some are by value
{/*...*/}
bool foo(/*...*/)
{}
};
And I don't want repeatly call bar1/bar2, etc. and then check the return value again and again, so I wrote a macro and variadic template to handle those things
#define help_macro(object, memfn, ...) help_func(#object "." #memfn, \
object, &decltype(object)::memfn, ##__VA_ARGS__)
template<class T, typename Func, typename... Args>
void help_func(char const * name, T &&object, Func memfn, Args&&... args)
{
auto ret = (object.*memfn)(forward<Args>(args)...);
cout<<name<<":\t"
<<(ret ? "OK" : "Oops") // maybe I'll throw an exception here
<<endl;
}
And use it like this
int i = 0;
Test t;
help_macro(t, bar, i, 'a');
It works on g++-4.7/Debian, but ICC13.0/Win refuses to compile it(a very strange error message)
main.cpp(37): error : type name is not allowed
help_macro(t, bar, i, 'a');
^
main.cpp(37): error : expected a ")"
help_macro(t, bar, i, 'a');
^
I turn on the C++11 for ICC, and confirmed that ICC13 support variadic template and decltype
Do I use it incorrectly or it's ICC's problem?

Edit: Having actually bothered to test my theory it turns out I was wrong, in that context decltype(t) is Test as can be shown by a static_assert(std::is_same<decltype(t), Test>::value, "not a reference")
So ICC (or the EDG front end it uses) probably just doesn't properly support using decltype in nested-name-specifiers, which was changed by DR 743
Using std::decay does make ICC accept it though, and so is a useful workaround.
Original, wrong, answer:
I think ICC is right here, decltype(object) is actually Test& and a reference type cannot have members, so &decltype(t)::memfn is ill-formed.
The code can be simplified to:
struct Test {
void foo() {}
};
int main()
{
Test t;
auto p = &decltype(t)::foo;
}
Which G++ and Clang accept, but ICC rejects, correctly IMHO.
You can fix it by using std::remove_reference or std::decay
#include <type_traits>
// ...
Test t;
auto p = &std::decay<decltype(t)>::type::foo;

I think the reason is there is no 'bar' function in class Test but not sure as I don't have access to this compiler. However the error message you posted shows there is an attempt to use 'bar'.
The following works on both gcc and clang
class Test {
public:
bool bar1(int &i, char c) // some arguments are passed by ref, some are by value
{return true;}
bool bar2(int &i, char c)
{return true;}
};
#define help_macro(object, memfn, ...) help_func(#object "." #memfn, \
object, &decltype(object)::memfn, ##__VA_ARGS__)
template<class T, typename Func, typename... Args>
void help_func(char const * name, T &&object, Func memfn, Args&&... args)
{
auto ret = (object.*memfn)(std::forward<Args>(args)...);
std::cout<<name<<":\t"
<<(ret ? "OK" : "Oops") // maybe I'll throw an exception here
<<std::endl;
}
int main()
{
int i = 0;
Test t;
//help_macro(t, bar, i, 'a');
help_macro(t, bar2, i, 'a');
}

Related

Is it possible to assign and verify a constexpr structure in C++14?

I implemented a getop() in C++. This is a class with all sorts of bells and whistles.
One of those bells would be a way to verify that the user enters valid options at compile time. Already I have part of that for the flags (not shown here) but I've been trying to make it work for the struct option and at this time I've not had much success.
First of all, the code allows me to define an array of options using the define_option() function. I want to be able to specify the fields of the option structure in any order and have some sanity checks on them. So I use a list of arguments to a template function. Each argument is a class which gets instantiated on the spot and then the define_option() selects the correct class for each field, extracting the value.
Up to here, everything works like a charm. Pretty basic C++.
Where I'm having a problem is inside the define_option() class. Say for instance that I were to try the following:
... define_option(...)
{
...
option opt = { ... };
static_assert(opt.f_short_name != '\0', "this failed");
...
}
Here I get an error. static_assert() tells me that opt is not constant.
a.cpp:168:1: error: non-constant condition for static assertion
So next my step is to mark the opt variable a constexpr (something the error says to do to resolve the static_assert().)
... define_option(...)
{
...
constexpr option opt = { ... };
...
}
Now even without the static_assert(), the code doesn't compile. I get the following error:
a.cpp:168:5: error: ‘args#0’ is not a constant expression
I'm thinking that it's not really doable from within the define_option() function, even though it's possible to check the resulting list of options as shown in the working example below. So in the end the opt global variable is a static fully defined at compile time (no code necessary to re-work on the table at runtime) but that doesn't help me since I can't make sure that the arguments for each option will work as expected.
I have an online running sample on coliru.
// compiled with: g++ -std=c++14 -o a ~/tmp/a.cpp
//
#include <iostream>
typedef char32_t short_name_t;
constexpr short_name_t NO_SHORT_NAME = L'\0';
struct option
{
short_name_t f_short_name = NO_SHORT_NAME;
char const * f_name = nullptr;
};
template<typename T, T default_value>
class OptionValue
{
public:
typedef T value_t;
constexpr OptionValue<T, default_value>()
: f_value(default_value)
{
}
constexpr OptionValue<T, default_value>(T const v)
: f_value(v)
{
}
constexpr value_t get() const
{
return f_value;
}
private:
value_t f_value;
};
class ShortName
: public OptionValue<short_name_t, NO_SHORT_NAME>
{
public:
constexpr ShortName()
: OptionValue<short_name_t, NO_SHORT_NAME>()
{
}
constexpr ShortName(short_name_t name)
: OptionValue<short_name_t, NO_SHORT_NAME>(name)
{
}
};
class Name
: public OptionValue<char const *, nullptr>
{
public:
constexpr Name()
: OptionValue<char const *, nullptr>()
{
}
constexpr Name(char const * name)
: OptionValue<char const *, nullptr>(name)
{
}
};
template<typename T, typename F, class ...ARGS>
constexpr typename std::enable_if<std::is_same<T, F>::value, typename T::value_t>::type find_option(F first, ARGS ...args)
{
return first.get();
}
template<typename T, typename F, class ...ARGS>
constexpr typename std::enable_if<!std::is_same<T, F>::value, typename T::value_t>::type find_option(F first, ARGS ...args)
{
return find_option<T>(args...);
}
template<class ...ARGS>
constexpr option define_option(ARGS ...args)
{
option opt =
{
.f_short_name = find_option<ShortName >(args..., ShortName()),
.f_name = find_option<Name >(args...),
};
return opt;
}
constexpr option const opt[] =
{
define_option(
Name("--help"),
ShortName('h')
)
};
// this test works as expected here
// but it does not work from inside define_option()
//
static_assert(opt[0].f_name[0] != '-', "Wrong start?!");
int main(int argc, char * argv [])
{
std::cerr << "opt[0].f_short_name = " << opt[0].f_short_name << std::endl;
return 0;
}
At this time I'm limited to C++14. If there is a C++17 solution, I'd still be interested.
Just add something that makes the call non-constant. Say, throw an exception.
template<class ...ARGS>
constexpr option define_option(ARGS ...args)
{
option opt =
{
.f_short_name = find_option<ShortName >(args..., ShortName()),
.f_name = find_option<Name >(args...),
};
if(/* check fails */) throw something;
return opt;
}
Then when you try to do
constexpr option const opt[] =
{
define_option(
Name("--help"),
ShortName('h')
)
};
and the check fails, the compiler will complain that this call to define_option is not a constant expression and cannot be used to initialize a constexpr variable.
You can even rig something to produce a linker error if this function is ever called at runtime. See e.g. this question.

Clang and GCC different behavior when resolving variadic function template overload

Consider this code:
#include <utility>
int foo_i(int x) { return x + 1; }
char foo_c(char x) { return x + 1; }
using II = int (*)(int);
using CC = char (*)(char);
template<typename F>
struct fn {
F f;
template<typename... Args>
decltype(auto) operator()(Args&&... args) const
{
return f(std::forward<Args>(args)...);
}
};
struct fn_2 : private fn<II>, private fn<CC> {
fn_2(II fp1, CC fp2)
: fn<II>{fp1}
, fn<CC>{fp2}
{}
using fn<II>::operator();
using fn<CC>::operator();
};
int main()
{
fn_2 f(foo_i, foo_c);
f(42);
}
Basically, fn<T> stores a functor (not necessarily a function pointer) of type T, and its variadic operator() forwards everything to the functor.
This code compiles fine with gcc 4.9.2 through gcc 6.1, but is rejected by every clang version I've tried, even clang 3.8. clang complains that the call is ambiguous. (I'd appreciate it if someone can try compile it with VS, because I don't have access to it right now.)
Which compiler is right, and how can I work around this discrepancy?
UPDATE: Although I'm still not sure which compiler's behavior is (more) compliant to the standard, I've found a workaround: Specializing fn<T> on pointers to functions, and avoid the need to blindly use variadic operator(). (Well, we've still left out pointers to member functions... For now I'm going to ignore them. :/) Example:
template<typename F>
struct fn : private F {
using F::operator();
};
template<typename R, typename... Args>
struct fn<R (*)(Args...)> {
fn(R (*f)(Args...)) noexcept : f_(f) {}
R operator()(Args&&... args) const
{
return f_(std::forward<Args>(args)...);
}
private:
R (*f_)(Args...);
};
I think clang is right here to not compile the code as the operator() is clearly ambiguous. If you think about it, from the provided template signature for operator() it's not clear which function should be preferred. You will have to provide additional hints to the compiler based on your stored function in fn.
Here is my solution:
#include <utility>
#include <type_traits>
#include <iostream>
int foo(int x) { return x + 1; }
char foo(char x) { return x + 1; }
using II = int (*)(int);
using CC = char (*)(char);
template <bool... B>
struct bool_pack {};
template <bool... V>
using all_true = std::is_same<bool_pack<true, V...>, bool_pack<V..., true>>;
template <typename... Args> struct packed {};
template <typename T> struct func_traits;
template <typename R, typename... Args>
struct func_traits<R(*)(Args...)> {
using type = packed<Args...>;
};
template<typename F>
struct fn {
F f;
template<typename... Args,
typename std::enable_if<std::is_same<packed<Args...>, typename func_traits<F>::type>::value>::type* = nullptr>
auto operator()(Args&&... args) const
{
return f(std::forward<Args>(args)...);
}
};
struct fn_2 : private fn<II>, private fn<CC> {
fn_2(II fp1, CC fp2)
: fn<II>{fp1}
, fn<CC>{fp2}
{}
using fn<II>::operator();
using fn<CC>::operator();
};
int main()
{
fn_2 f(static_cast<II>(foo),
static_cast<CC>(foo));
std::cout << f(42) << std::endl;
std::cout << f('a') << std::endl;
}
Nothing fancy, but I am using enable_if to help compiler choose the correct version of operator() based upon the arity types of the stored function.
This is a GCC bug. Note that GCC always calls the fn<II> version, even if called with a parameter of type char. There is no way a compiler can tell which function template to call, because they have the exact same signature, and GCC is just picking one arbitrarily.
The code would work perfectly fine if char and int were independent types with no implicit conversions. However, since char and int can be implicitly converted between each other (yes, int to char can convert implicitly!), there may be an ambiguity in the call. GCC does the intuitive exception in selecting the call requiring no conversion at all, if present.
EDIT: I've been pointed out there is a templated argument that gets its own operator() function in here. This is something I definitely did not see.

C++ variadic template arguments method to pass to a method without variadic arguments

I have the following question, I really can't compile from all the questions and articles researched:
In C++, is it possible to have a method with variadic template arguments that specify types of arguments (as a meta-description type for parameters of in, out, in/out of a certain type, to be passed by value, by address etc.), to loop through these variadic arguments in order to instantiate variables of specified types, and be passed these variables to functions specified by a pointer in a template parameter, but these functions not having variadic parameters?
EDIT 1
I try here to detail, as pseudocode:
template <decltype(*Type::*Method), typename... Parameters>
static bool ExecuteMethod(JSContext *cx, unsigned argc, JS::Value *vp)
{
JS::CallArgs args = CallArgsFromVp(argc, vp);
loop through Parameters
{
Parameters[i]::Type p[i] <-- args[i];
}
ReturnType r = Method(p[0], p[1], p[2] .. p[n]); // the method does not have variadic parameters
...
}
where Method might be like:
int(*GetColor) ( int16 *color);
int(*GetFile) ( FilePath &file );
int(*WriteDocument) ( const FilePath &file, const char *fileFormatName, bool askForParms);
etc.
This comes out of wrapping needs.
The challenge is something missing in C++, reflection as in .net.
It is possible to instance an array of heterogeneous objects by looping through the variadic arguments somehow? Probably.
But how pass them to methods having no variadic arguments? I think it is not possible to assign that array of objects to functions like these three above without explicit wrappers, isn't it?
EDIT 2
I've got a lot of feed-back, but it is clear I was not specific enough.
I did not detailed too much because I've got complains in the past for being too specific. Indeed, I do not have easy implementations and I am a generic guy, not lazy, but I try to make a latter development faster.
Here is the source of the problem: I need to wrap Adobe Illustrator API, which exposes hundreds if not thousands of pointers to functions grouped in structs, called suites.
I try to have a javascript engine using SpiderMonkey.
I use Visual Studio 2015 compiler.
My approach is as follows:
I have several classes to wrap the API in order to add to SpiderMonkey's engine objects for all the suites. Each SpiderMonkey class, could be called as jsData, wraps a data type of Adobe SDK, or a suite, jsSuite.
So far, I have used templates because SpiderMonkey forces me to add each function to its custom objects with a specific signature, like this:
bool jsAIDocumentSuite::WriteDocument(JSContext *cx, unsigned argc, JS::Value *vp)
{
...
}
and adding it to the custom object would be done like this:
const JSFunctionSpec jsAIDocumentSuite::fFunctions[] = {
...
JS_FN("WriteDocument", jsAIDocumentSuite::WriteDocument, 3, 0),
...
}
JS_FN is a SpiderMonkeyMacro.
Actually, this is, so far, less than 10% of the Adobe SDK.
The most are getters and setters with one parameter, passed by value or address or pointer, so I have replaced them by a generic function, like this:
template <typename jsType, typename jsReturnType, typename ReturnPrivateType = jsReturnType::PrivateType, typename jsParamType, typename ParamPrivateType = jsParamType::PrivateType, ReturnPrivateType(*Type::*Method)(ParamPrivateType&)>
static bool GetByRefMethod(JSContext *cx, unsigned argc, JS::Value *vp)
{
JS::CallArgs args = CallArgsFromVp(argc, vp);
try
{
ReturnPrivateType result;
ParamPrivateType ppt;
if (jsType::Suite() && (jsType::Suite()->*Method))
result = (jsType::Suite()->*Method)(ppt);
else
return false; // TODO throw a meaningful error
if ((jsReturnType::IsNoError(result)) && (argc > 0) && (args[0].isObject()))
{
JSObject *obj = &args[0].toObject();
JSObject *value = NULL;
if (!jsParamType::FromAIObject<jsParamType>(cx, &ppt, value))
return false;
if (!value)
return false;
jsProperty::SetProperty(cx, &obj, "value", value, true);
}
JSObject *obj = JS_NewObject(cx, &jsDataClass<jsReturnType>::fClass);
JS_SetPrivate(obj, new ReturnPrivateType(result));
args.rval().setObject(*obj);
}
EXCEPTION_CATCH_CONVERT();
return true;
}
A bit complicated, isn't it?
What is relevant, above, is:
The args variable holds the SpiderMonkey parameters passed in by its engine
Only one argument is passed here, ppt
The return type is one value, so it is easy to be handled
I use macros to inject the method in its variants (several short forms too, not so interesting here):
JS_FN(#GET_METHOD, (js##TYPE::GetByRefMethod<js##TYPE, RETURN_JS_TYPE, RETURN_PRIVATE_TYPE, PARAM_JS_TYPE, PARAM_PRIVATE_TYPE, &TYPE::GET_METHOD>), 1, 0)
I wish to be able to handle variable arguments, according to the statistics more philosophical, but interesting. The idea would be opposite to the C++, probably, and not as expected.
How would I expect it:
I wish to add variadic parameters meta-information, like:
template
static bool Method(JSContext *cx, unsigned argc, JS::Value *vp)
{
JS::CallArgs args = CallArgsFromVp(argc, vp);
try
{
ReturnPrivateType result;
*1st challenge: Loop through the variadic list of meta-parameters and create their corresponding object instances here and initialize the IN ones with values from the *args* collection passed by the SpiderMonkey engine*
if (jsType::Suite() && (jsType::Suite()->*Method))
result = (jsType::Suite()->*Method)(*2nd challenge: pass arguments here: probably by using a variadic macro?*);
else
return false; // TODO throw a meaningful error
if ((jsReturnType::IsNoError(result)) && (argc > 0) && (args[0].isObject()))
{
JSObject *obj = &args[0].toObject();
JSObject *value = NULL;
if (!jsParamType::FromAIObject<jsParamType>(cx, &ppt, value))
return false;
if (!value)
return false;
jsProperty::SetProperty(cx, &obj, "value", value, true);
}
JSObject *obj = JS_NewObject(cx, &jsDataClass<jsReturnType>::fClass);
JS_SetPrivate(obj, new ReturnPrivateType(result));
args.rval().setObject(*obj);
}
EXCEPTION_CATCH_CONVERT();
return true;
}
As you can see, it is not as C++ expected, it is a bit reversed, by trying to avoid writing templates to deduct the parameters, here, I know the parameters first and try to write a code to generate the right parameters by knowing their meta-information first and I have a clear set of types and I promise to write the right code to generate the correct wrappers. I don't need to validate much regarding the data of the parameters, as things are mostly passed without a huge business logic in the process.
EDIT 3
About the parameters meta-information, I could write a few types with statics to specify the data type of the parameter, whether it is a return type, whether it is an IN, an OUT or an IN/OUT parameter, its jsType etc..
They would be the variadic list of the template parameters function above.
I still am having some difficulty understanding exactly what you want to do, but this should let you call a function(without variardic parameters) using a variardic template function, getting the parameters from an array and allowing a conversion operation to apply to each parameter before being passed to the function:
#include <functional>
template<typename T, typename JST> T getParam(const JST& a)
{
//Do whatever conversion necessary
return a;
}
namespace detail
{
template<typename R, typename... Args, int... S> R jsCaller(std::function<R(Args...)> f, seq<S...>, const JS::CallArgs& args)
{
return f(getParam<Args, /*Whatever type should go here */>(args[S])...);
}
}
//Actually use this to call the function and get the result
template<typename R, typename... Args> R jsCall(std::function<R(Args...)> f, const JS::CallArgs& args)
{
return detail::jsCaller(f, GenSequence<sizeof...(Args)>(), args);
}
Where GenSequence extends seq<0, 1, 2, ... , N - 1> and can be implemented as follows:
template<int... N>
struct seq {};
template<int N, int... S>
struct gens : gens<N-1, N-1, S...> {};
template<int... S>
struct gens<0, S...>
{
typedef seq<S...> type;
};
template<int N> using GenSequence<N> = typename gens<N>::type;
This creates a parameter pack of integers, and expands the function call using them- See this question.
You can call your method using jsCall:
Result r = jsCall((Method), args);
Assuming Method can be converted to std::function- if not, you can still do it by making a lambda which conforms to std::function. Does this solve the problem?
[Continued from part 1: https://stackoverflow.com/a/35109026/5386374 ]
There is an issue, however. We had to change the way our code is written to accomodate ExecuteMethod(), which may not always be possible. Is there a way around that, so that it functions exactly the same as your previously specified ExecuteMethod(), and doesn't need to take the variable it modifies as a macro parameter? The answer is... yes!
// Variadic function-like macro to automatically create, use, and destroy functor.
// Uncomment whichever one is appropriate for the compiler used.
// (The difference being that Visual C++ automatically removes the trailing comma if the
// macro has zero variadic arguments, while GCC needs a hint in the form of "##" to tell
// it to do so.)
// Instead of a do...while structure, we can just use a temporary Executor directly.
// MSVC:
// #define ExecuteMethod(M, ...) Executor<decltype(&M), decltype(&M)>{}(M, __VA_ARGS__)
// GCC:
#define ExecuteMethod(M, ...) Executor<decltype(&M), decltype(&M)>{}(M, ##__VA_ARGS__)
// For your example function WriteDocument(), defined as
// int WriteDocument(const FilePath &file, const char *fileFormatName, bool askForParms);
bool c = ExecuteMethod(WriteDocument, file, fileFormatName, askForParams);
This is all well and good, but there is one more change we can make to simplify things without impacting performance. At the moment, this functor can only take function pointers (and maybe lambdas, I'm not familiar with their syntax), not other types of function objects. If this is intended, it means that we can rewrite it to do away with the first template parameter (the entire signature), since the second and third parameters are themselves components of the signature.
// Default functor.
template<typename... Ts>
struct Executor { };
// General case.
template<typename ReturnType, typename... Params>
struct Executor<ReturnType (*)(Params...)> {
private:
// Instead of explicitly taking M as a parameter, create it from
// the other parameters.
using M = ReturnType (*)(Params...);
public:
// Parameter match:
bool operator()(M method, Params... params) {
ReturnType r = method(params...);
// ...
}
// Parameter mismatch:
template<typename... Invalid_Params>
bool operator()(M method, Invalid_Params... ts) {
// Handle parameter type mismatch here.
}
};
// Special case to catch void return type.
template<typename... Params>
struct Executor<void (*)(Params...)> {
private:
// Instead of explicitly taking M as a parameter, create it from
// the other parameters.
using M = void (*)(Params...);
public:
// Parameter match:
bool operator()(M method, Params... params) {
method(params...);
// ...
}
// Parameter mismatch:
template<typename... Invalid_Params>
bool operator()(M method, Invalid_Params... ts) {
// Handle parameter type mismatch here.
}
};
// Variadic function-like macro to automatically create, use, and destroy functor.
// Uncomment whichever one is appropriate for the compiler used.
// (The difference being that Visual C++ automatically removes the trailing comma if the
// macro has zero variadic arguments, while GCC needs a hint in the form of "##" to tell
// it to do so.)
// Instead of a do...while structure, we can just use a temporary Executor directly.
// MSVC:
// #define ExecuteMethod(M, ...) Executor<decltype(&M)>{}(M, __VA_ARGS__)
// GCC:
#define ExecuteMethod(M, ...) Executor<decltype(&M)>{}(M, ##__VA_ARGS__)
// Note: If your compiler doesn't support C++11 "using" type aliases, replace them
// with the following:
// typedef ReturnType (*M)(Params...);
This results in cleaner code, but, as mentioned, limits the functor to only accepting function pointers.
When used like this, the functor expects parameters to be an exact match. It can handle reference-ness and cv-ness correctly, but may have issues with rvalues, I'm not sure. See here.
As to how to use this with your JSContext... I'm honestly not sure. I haven't learned about contexts yet, so someone else would be more helpful for that. I would suggest checking if one of the other answers here would be more useful in your situation, in all honesty.
Note: I'm not sure how easy it would be to modify the functor to work if its function parameter is a functor, lambda, std::function, or anything of the sort.
Note 2: As before, I'm not sure if there would be any negative effects on performance for doing something like this. There's likely a more efficient way, but I don't know what it would be.
I came up with the following C++11 solution, which gives the basic idea. It could very easily be improved, however, so I welcome suggestions. Live test here.
#include <iostream>
#include <tuple>
using namespace std;
// bar : does something with an arbitrary tuple
// (no variadic template arguments)
template <class Tuple>
void bar(Tuple t)
{
// .... do something with the tuple ...
std::cout << std::tuple_size<Tuple>::value;
}
// foo : takes a function pointer and an arbitrary number of other
// arguments
template <class Func, typename... Ts>
void foo(Func f, Ts... args_in)
{
// construct a tuple containing the variadic arguments
std::tuple<Ts...> t = std::make_tuple(args_in...);
// pass this tuple to the function f
f(t);
}
int main()
{
// this is not highly refined; you must provide the types of the
// arguments (any suggestions?)
foo(bar<std::tuple<int, const char *, double>>, 123, "foobar", 43.262);
return 0;
}
Edit: After seeing your "Edit 2", I don't believe this is the proper solution. Leaving it up for reference, though.
I believe I've found a potential solution that catches reference-ness, too. Scroll down to the bottom, to the "Edit 4" section.
If you're asking whether it's possible to dynamically check template argument types, you can. I'll start with a general example of how to use std::true_type and std::false_type to overload based on whether a specified condition is met, then move on to your problem specifically. Consider this:
#include <type_traits>
namespace SameComparison {
// Credit for the contents of this namespace goes to dyp ( https://stackoverflow.com/a/20047561/5386374 )
template<class T, class...> struct are_same : std::true_type{};
template<class T, class U, class... TT> struct are_same<T, U, TT...> :
std::integral_constant<bool, std::is_same<T, U>{} && are_same<T, TT...>{} >{};
} // namespace SameComparison
template<typename T> class SomeClass {
public:
SomeClass() = default;
template<typename... Ts> SomeClass(T arg1, Ts... args);
~SomeClass() = default;
void func(T arg1);
template<typename U> void func(U arg1);
template<typename... Ts> void func(T arg1, Ts... args);
template<typename U, typename... Ts> void func(U arg1, Ts... args);
// ...
private:
template<typename... Ts> SomeClass(std::true_type x, T arg1, Ts... args);
template<typename... Ts> SomeClass(std::false_type x, T arg1, Ts... args);
// ...
};
// Constructors:
// -------------
// Public multi-argument constructor.
// Passes to one of two private constructors, depending on whether all types in paramater pack match T.
template<typename T> template<typename... Ts> SomeClass<T>::SomeClass(T arg1, Ts... args) :
SomeClass(SameComparison::are_same<T, Ts...>{}, arg1, args...) { }
// All arguments match.
template<typename T> template<typename... Ts> SomeClass<T>::SomeClass(std::true_type x, T arg1, Ts... args) { }
// One or more arguments is incorrect type.
template<typename T> template<typename... Ts> SomeClass<T>::SomeClass(std::false_type x, T arg1, Ts... args) {
static_assert(x.value, "Arguments wrong type.");
}
/*
Note that if you don't need to use Ts... in the parameter list, you can combine the previous two into a single constructor:
template<typename T> template<bool N, typename... Ts> SomeClass<T>::SomeClass(std::integral_constant<bool, N> x, T arg1, Ts... args) {
static_assert(x.value, "Arguments wrong type.");
}
x will be true_type (value == true) on type match, or false_type (value == false) on type mismatch. Haven't thoroughly tested this, just ran a similar function through an online compiler to make sure it could determine N.
*/
// Member functions:
// -----------------
// Single argument, type match.
template<typename T> void SomeClass<T>::func(T arg1) {
// code
}
// Single argument, type mismatch.
// Also catches true_type from multi-argument functions after they empty their parameter pack, and silently ignores it.
template<typename T> template<typename U> void SomeClass<T>::func(U arg1) {
if (arg1 != std::true_type{}) {
std::cout << "Argument " << arg1 << " wrong type." << std::endl;
}
}
// Multiple arguments, argument 1 type match.
template<typename T> template<typename... Ts> void SomeClass<T>::func(T arg1, Ts... args) {
func(arg1);
func(args...);
// func(SameComparison::are_same<T, Ts...>{}, vals...);
}
// Multiple arguments, argument 1 type mismatch.
template<typename T> template<typename U, typename... Ts> void SomeClass<T>::func(U arg1, Ts... args) {
// if (arg1 != std::true_type{}) {
// std::cout << "Argument " << arg1 << " wrong type." << std::endl;
// }
func(vals...);
}
First, SameComparison::are_same there is an extension of std::is_same, that applies it to an entire parameter pack. This is the basis of the check, with the rest of the example showing how it can be used. The lines commented out of the last two functions show how it could be applied there, as well.
Now, onto your problem specifically. Since you know what the methods are, you can make similar comparison structs for them.
int (*GetColor) ( int16_t *color);
int(*GetFile) ( FilePath &file );
int(*WriteDocument) ( const FilePath &file, const char *fileFormatName, bool askForParms);
Could have...
namespace ParameterCheck {
template<typename T, typename... Ts> struct parameter_match : public std::false_type {};
// Declare (GetColor, int16_t*) valid.
template<> struct parameter_match<int (*)(int16_t*), int16_t*> : public std::true_type {};
// Declare (GetFile, FilePath&) valid.
// template<> struct parameter_match<int (*)(FilePath&), FilePath&> : public std::true_type {}; // You'd think this would work, but...
template<> struct parameter_match<int (*)(FilePath&), FilePath> : public std::true_type {}; // Nope!
// For some reason, reference-ness isn't part of the templated type. It acts as if it was "template<typename T> void func(T& arg)" instead.
// Declare (WriteDocument, const FilePath&, const char*, bool) valid.
// template<> struct parameter_match<int (*)(const FilePath&, const char*, bool), const FilePath, const char*, bool> : public std::true_type {};
// template<> struct parameter_match<int (*)(const FilePath&, const char*, bool), const FilePath&, const char*, bool> : public std::true_type {};
template<> struct parameter_match<int (*)(const FilePath&, const char*, bool), FilePath, const char*, bool> : public std::true_type {};
// More reference-as-template-parameter wonkiness: Out of these three, only the last works.
} // namespace ParameterCheck
Here, we make a general-case struct that equates to std::false_type, then specialise it so that specific cases are true_type instead. What this does is tell the compiler, "These parameter lists are good, anything else is bad," where each list starts with a function pointer and ends with the arguments to the function. Then, you can do something like this for your caller:
// The actual calling function.
template<typename Func, typename... Ts> void caller2(std::true_type x, Func f, Ts... args) {
std::cout << "Now calling... ";
f(args...);
}
// Parameter mismatch overload.
template<typename Func, typename... Ts> void caller2(std::false_type x, Func f, Ts... args) {
std::cout << "Parameter list mismatch." << std::endl;
}
// Wrapper to check for parameter mismatch.
template<typename Func, typename... Ts> void caller(Func f, Ts... args) {
caller2(ParameterCheck::parameter_match<Func, Ts...>{}, f, args...);
}
As for return type deduction... that depends on where you want to deduce it:
Determine variable type from contents: Use auto when declaring the variable.
Determine return type from passed function return type: If your compiler is C++14-compatible, that's easy. Just use auto. [VStudio 2015 and GCC 4.8.0 (with -std=c++1y) are compatible with auto return type.]
The former can be done like this:
int i = 42;
int func1() { return 23; }
char func2() { return 'c'; }
float func3() { return -0.0f; }
auto a0 = i; // a0 is int.
auto a1 = func1(); // a1 is int.
auto a2 = func2(); // a2 is char.
auto a3 = func3(); // a3 is float.
The latter, however, is more complex.
std::string stringMaker() {
return std::string("Here, have a string!");
}
int intMaker() {
return 5;
}
template<typename F> auto automised(F f) {
return f();
}
// ...
auto a = automised(stringMaker); // a is std::string.
auto b = automised(intMaker); // a is int.
If your compiler isn't compatible with auto or decltype(auto) return type... well, it's a bit more verbose, but we can do this:
namespace ReturnTypeCapture {
// Credit goes to Angew ( https://stackoverflow.com/a/18695701/5386374 )
template<typename T> struct ret_type;
template<typename RT, typename... Ts> struct ret_type<RT (*)(Ts...)> {
using type = RT;
};
} // namespace ReturnTypeCapture
// ...
std::string f1() {
return std::string("Nyahaha.");
}
int f2() {
return -42;
}
char f3() {
return '&';
}
template<typename R, typename F> auto rtCaller2(R r, F f) -> typename R::type {
return f();
}
template<typename F> void rtCaller(F f) {
auto a = rtCaller2(ReturnTypeCapture::ret_type<F>{}, f);
std::cout << a << " (type: " << typeid(a).name() << ")" << std::endl;
}
// ...
rtCaller(f1); // Output (with gcc): "Nyahaha. (type: Ss)"
rtCaller(f2); // Output (with gcc): "-42 (type: i)"
rtCaller(f3); // Output (with gcc): "& (type: c)"
Furthermore, we can simplify it even more, and check the return type without a separate wrapper.
template<typename F> auto rtCaller2(F f) -> typename ReturnTypeCapture::ret_type<F>::type {
return f();
}
template<typename F> void rtCaller(F f) {
auto a = rtCaller2(f);
std::cout << a << " (type: " << typeid(a).name() << ")" << std::endl;
}
// ...
rtCaller(f1); // Output (with gcc): "Nyahaha. (type: Ss)"
rtCaller(f2); // Output (with gcc): "-42 (type: i)"
rtCaller(f3); // Output (with gcc): "& (type: c)"
// Same output.
Having that sticking off the end there is really ugly, though, so can't we do better than that? The answer is... yes! We can use an alias declaration to make a typedef, leaving a cleaner name. And thus, the final result here is:
namespace ReturnTypeCapture {
// Credit goes to Angew ( https://stackoverflow.com/a/18695701/5386374 )
template<typename T> struct ret_type;
template<typename RT, typename... Ts> struct ret_type<RT (*)(Ts...)> {
using type = RT;
};
} // namespace ReturnTypeCapture
template <typename F> using RChecker = typename ReturnTypeCapture::ret_type<F>::type;
std::string f1() { return std::string("Nyahaha."); }
int f2() { return -42; }
char f3() { return '&'; }
template<typename F> auto rtCaller2(F f) -> RChecker<F> {
return f();
}
template<typename F> void rtCaller(F f) {
auto a = rtCaller2(f);
std::cout << a << " (type: " << typeid(a).name() << ")" << std::endl;
}
So now, if we combine parameter checking & return type deduction...
// Parameter match checking.
namespace ParameterCheck {
template<typename T, typename... Ts> struct parameter_match : public std::false_type {};
// Declare (GetColor, int16_t*) valid.
template<> struct parameter_match<int (*)(int16_t*), int16_t*> : public std::true_type {};
// Declare (GetFile, FilePath&) valid.
template<> struct parameter_match<int (*)(FilePath&), FilePath> : public std::true_type {};
// Declare (WriteDocument, const FilePath&, const char*, bool) valid.
template<> struct parameter_match<int (*)(const FilePath&, const char*, bool), FilePath, const char*, bool> : public std::true_type {};
// Declare everything without a parameter list valid.
template<typename T> struct parameter_match<T (*)()> : public std::true_type { };
} // namespace ParameterCheck
// Discount return type deduction:
namespace ReturnTypeCapture {
// Credit goes to Angew ( https://stackoverflow.com/a/18695701/5386374 )
template<typename T> struct ret_type;
template<typename RT, typename... Ts> struct ret_type<RT (*)(Ts...)> {
using type = RT;
};
} // namespace ReturnTypeCapture
// Alias declarations:
template<typename F, typename... Ts> using PChecker = ParameterCheck::parameter_match<F, Ts...>;
template<typename F> using RChecker = typename ReturnTypeCapture::ret_type<F>::type;
// ---------------
int GetColor(int16_t* color);
int GetFile(FilePath& file);
int WriteDocument(const FilePath& file, const char* fileFormatName, bool askForParams);
std::string f1() { return std::string("Nyahaha."); }
int f2() { return -42; }
char f3() { return '&'; }
// ---------------
// Calling function (C++11):
// The actual calling function.
template<typename Func, typename... Ts> auto caller2(std::true_type x, Func f, Ts... args) -> RChecker<Func> {
std::cout << "Now calling... ";
return f(args...);
}
// Parameter mismatch overload.
template<typename Func, typename... Ts> auto caller2(std::false_type x, Func f, Ts... args) -> RChecker<Func> {
std::cout << "Parameter list mismatch." << std::endl;
return static_cast<RChecker<Func> >(0); // Just to make sure we don't break stuff.
}
// Wrapper to check for parameter mismatch.
template<typename Func, typename... Ts> auto caller(Func f, Ts... args) -> RChecker<Func> {
// return caller2(ParameterCheck::parameter_match<Func, Ts...>{}, f, args...);
return caller2(PChecker<Func, Ts...>{}, f, args...);
}
// ---------------
// Calling function (C++14):
// The actual calling function.
template<typename Func, typename... Ts> auto caller2(std::true_type x, Func f, Ts... args) {
std::cout << "Now calling... ";
return f(args...);
}
// Parameter mismatch overload.
template<typename Func, typename... Ts> auto caller2(std::false_type x, Func f, Ts... args) {
std::cout << "Parameter list mismatch." << std::endl;
}
// Wrapper to check for parameter mismatch.
template<typename Func, typename... Ts> auto caller(Func f, Ts... args) {
// return caller2(ParameterCheck::parameter_match<Func, Ts...>{}, f, args...);
return caller2(PChecker<Func, Ts...>{}, f, args...);
}
You should be able to get the functionality you want out of this, I believe. The only caveat is that if you do it this way, you need to explicitly declare functions valid in ParameterCheck, by making a template specialisation for the function & its parameter list, derived from std::true_type instead of std::false_type. I'm not sure if there's a way to get true dynamic parameter list checking, but it's a start.
[I'm not sure if you can just overload caller() or if you explicitly need to use caller2() as well. All my attempts to overload caller() via template parameters ended up crashing the compiler; for some reason, it chose template<typename Func, typename... Ts> void caller(Func f, Ts... args) as a better match for caller(std::true_type, f, args...) than template<typename Func, typename... Ts> caller(std::true_type x, Func f, Ts... args), even with the latter listed before the former, and tried to recursively expand it until it ran out of memory. (Tested on two online gcc compilers: Ideone, and TutorialsPoint's compiler (with -std=c++11). I'm not sure if this is a gcc problem, or if I was a bit off about how template matching works. Unfortunately, the online VStudio compiler is down for maintenance, and the only version of VS I have available to me offline at the moment doesn't support variadic templates, so I can't check which is the case.) Unless someone says otherwise, or says how to fix that particular issue, it's probably best to just use caller() as a wrapper & caller2() to do the heavy lifting.]
Examples of pretty much everything here that would be relevant to your problem: here
Also, note that you can't easily pull individual arguments from a parameter pack. You can use recursion to strip arguments off the front a few at a time, you can use them to initialise member variables in a constructor's initialisation list, you can check how many arguments are in the pack, you can specialise it (as we did for parameter_match), & you can pass the whole pack to a function that takes the right number of arguments, but I believe that's it at the moment. This can make them a bit more awkward than C-style varargs at times, despite being more efficient. However, if your ExecuteMethod()'s argument list consists of a function and its argument list, and nothing else, this isn't an issue. As long as the parameter match succeeds, we can just give the entire pack to the passed function, no questions asked. On that note, we can rewrite ExecuteMethod() into something like...
// Not sure what cx is, leaving it alone.
// Assuming you wanted ExecuteMethod to take parameters in the order (cx, function, function_parameter_list)...
// Parameter list match.
template<typename M, typename... Parameters>
static bool ExecuteMethodWorker(std::true_type x, JSContext* cx, M method, Parameters... params)
{
auto r = method(params...);
// ...
}
// Parameter list mismatch.
template<typename M, typename... Parameters>
static bool ExecuteMethodWorker(std::false_type x, JSContext* cx, M method, Parameters... params)
{
// Handle parameter type mismatch here.
// Omit if not necessary, though it's likely better to use it to log errors, terminate, throw an exception, or something.
}
// Caller.
template<typename M, typename... Parameters>
static bool ExecuteMethod(JSContext* cx, M method, Parameters... params)
{
return ExecuteMethodWorker(PChecker<M, Parameters...>{}, cx, method, params...);
}
Make sure to either prototype or define the worker functions before ExecuteMethod(), so the compiler can resolve the call properly.
(Apologies for any typoes I may have missed anywhere in there, I'm a bit tired.)
Edit: I've located the problem with passing references to a template. It seems that using templates to determine types does indeed remove reference-ness in and of itself, hence notation like template<typename T> void func(T&) for functions that take a reference. Sadly, I'm not yet sure how to fix this issue. I did, however, come up with a new version of PChecker that dynamically reflects types for any function that doesn't use reference types. So far, however, you still need to add references manually, and non-const references probably won't work properly for now.
namespace ParameterCheck {
namespace ParamGetter {
// Based on an answer from GManNickG ( https://stackoverflow.com/a/4693493/5386374 )
// Turn the type list into a single type we can use with std::is_same.
template<typename... Ts> struct variadic_typedef { };
// Generic case, to catch passed parameter types list.
template<typename... Ts> struct variadic_wrapper {
using type = variadic_typedef<Ts...>;
};
// Special case to catch void parameter types list.
template<> struct variadic_wrapper<> {
using type = variadic_typedef<void>;
};
// Generic case to isolate parameter list from function signature.
template<typename RT, typename... Ts> struct variadic_wrapper<RT (*)(Ts...)> {
using type = variadic_typedef<Ts...>;
};
// Special case to isolate void parameter from function signature.
template<typename RT> struct variadic_wrapper<RT (*)()> {
using type = variadic_typedef<void>;
};
} // namespace ParamGetter
template<typename... Ts> using PGetter = typename ParamGetter::variadic_wrapper<Ts...>::type;
// Declare class template.
template<typename... Ts> struct parameter_match;
// Actual class. Becomes either std::true_type or std::false_type.
template<typename F, typename... Ts> struct parameter_match<F, Ts...> : public std::integral_constant<bool, std::is_same<PGetter<F>, PGetter<Ts...> >{}> {};
// Put specialisations for functions with const references here.
} // namespace ParameterCheck
template<typename F, typename... Ts> using PChecker = ParameterCheck::parameter_match<F, Ts...>;
See here.
--
Edit 2: Okay, can't figure out how to grab the passed function's parameter list and use it directly. It might be possible using tuples, perhaps using the rest of GManNickG's code (the convert_in_tuple struct), but I haven't looked into them, and don't really know how to grab the entire type list from a tuple at the same time, or if it's even possible. [If anyone else knows how to fix the reference problem, feel free to comment.]
If you're only using references to minimise passing overhead, and not to actually change data, you should be fine. If your code uses reference parameters to modify the data that the parameter is pointing to, however, I'm not sure how to help you. Sorry.
--
Edit 3: It looks like RChecker might not be as necessary for C++11 function forwarding, we can apparently use decltype([function call]) for that. So...
// caller2(), using decltype. Valid, as args... is a valid parameter list for f.
template<typename Func, typename... Ts> auto caller2(std::true_type x, Func f, Ts... args) -> decltype(f(args...)) {
std::cout << "Now calling... ";
return f(args...);
}
// Parameter mismatch overload.
// decltype(f(args...)) would be problematic, since args... isn't a valid parameter list for f.
template<typename Func, typename... Ts> auto caller2(std::false_type x, Func f, Ts... args) -> RChecker<Func> {
std::cout << "Parameter list mismatch." << std::endl;
return static_cast<RChecker<Func> >(0); // Make sure we don't break stuff.
}
// Wrapper to check for parameter mismatch.
// decltype(caller2(PChecker<Func, Ts...>{}, f, args...)) is valid, but would be more verbose than RChecker<Func>.
template<typename Func, typename... Ts> auto caller(Func f, Ts... args) -> RChecker<Func> {
// return caller2(ParameterCheck::parameter_match<Func, Ts...>{}, f, args...);
return caller2(PChecker<Func, Ts...>{}, f, args...);
}
However, as noted, decltype can have issues when it can't find a function call that matches what it's passed exactly. So, for any case where the parameter mismatch version of caller2() is called, trying to use decltype(f(args...)) to determine return type would likely cause issues. However, I'm not sure if decltype(auto), introduced in C++14, would have that issue.
Also, in C++14-compatible compilers, it's apparently better to use decltype(auto) than just auto for automatic return type determination; auto doesn't preserve const-ness, volatile-ness, or reference-ness, while decltype(auto) does. It can be used either as a trailing return type, or as a normal return type.
// caller2(), using decltype(auto).
template<typename Func, typename... Ts> decltype(auto) caller2(std::true_type x, Func f, Ts... args) {
std::cout << "Now calling... ";
return f(args...);
}
decltype(auto) can also be used when declaring variables. See here for more information.
Edit 4: I believe I may have found a potential solution that preserves the passed function's parameter list properly, using functors. However, it may or may not create unwanted overhead, I'm not sure.
// Default functor.
template<typename... Ts>
struct Executor { };
// General case.
template<typename M, typename ReturnType, typename... Params>
struct Executor<M, ReturnType (*)(Params...)> {
public:
// Parameter match:
bool operator()(M method, Params... params) {
ReturnType r = method(params...);
// ...
}
// Parameter mismatch:
template<typename... Invalid_Params>
bool operator()(M method, Invalid_Params... ts) {
// Handle parameter type mismatch here.
}
};
// Special case to catch void return type.
template<typename M, typename... Params>
struct Executor<M, void (*)(Params...)> {
public:
// Parameter match:
bool operator()(M method, Params... params) {
method(params...);
// ...
}
// Parameter mismatch:
template<typename... Invalid_Params>
bool operator()(M method, Invalid_Params... ts) {
// Handle parameter type mismatch here.
}
};
// Variadic function-like macro to automatically create, use, and destroy functor.
// Uncomment whichever one is appropriate for the compiler used.
// (The difference being that Visual C++ automatically removes the trailing comma if the
// macro has zero variadic arguments, while GCC needs a hint in the form of "##" to tell
// it to do so.)
// Also note that the "do { ... } while (false)" structure is used to swallow the trailing
// semicolon, so it doesn't inadvertently break anything; most compilers will optimise it
// out, leaving just the code inside.
// (Source: https://gcc.gnu.org/onlinedocs/cpp/Swallowing-the-Semicolon.html )
// MSVC:
// #define ExecuteMethod(C, M, ...) \
// do { \
// Executor<decltype(&M), decltype(&M)> temp; \
// C = temp(M, __VA_ARGS__); \
// } while (false)
// GCC:
#define ExecuteMethod(C, M, ...) \
do { \
Executor<decltype(&M), decltype(&M)> temp; \
C = temp(M, ##__VA_ARGS__); \
} while (false)
In this case, you can use it as:
ExecuteMethod(return_value_holder, function_name, function_parameter_list);
Which expands to...
do {
Executor<decltype(&function_name), decltype(&function_name)> temp;
return_value_holder = temp(function_name, function_parameter_list);
} while (false);
With this, there's no need to manually go through the parameter pack and make sure each one matches the passed function's parameters. As the passed function's parameter list is quite literally built into Executor as Params..., we can simply overload the function call operator based on whether the arguments it was passed match Params... or not. If the parameters match the function, it calls the Parmas... overload; if they don't, it calls the Invalid_Params... overload. A bit more awkward than true reflection, IMO, but it seems to match everything properly.
Note that:
I'm not sure whether using functors liberally can cause any performance or memory use overhead. I'm... not all that familiar with them at the moment.
I don't know if it's possible to combine the general case and the "void return type" special case into a single functor. The compiler complained when I tried, but I'm not sure if it's because it isn't possible or because I was doing it wrong.
Considering #2, when modifying this version of ExecuteMethod()'s parameters, you have to modify it and both versions of Executor to match.
Like so, where JSContext* cx is added to the parameter list:
template<typename M, typename ReturnType, typename... Params>
struct Executor<M, ReturnType (*)(Params...)> {
public:
bool operator()(JSContext* cx, M method, Params... params);
};
template<typename M, typename... Params>
struct Executor<M, void (*)(Params...)> {
public:
bool operator()(JSContext* cx, M method, Params... params);
};
#define ExecuteMethod(C, cx, M, ...) \
do { \
Executor<decltype(&M), decltype(&M)> temp; \
C = temp(cx, M, ##__VA_ARGS__); \
} while (false)
This may be the solution, but it requires further testing to see if it has any negative impacts on performance. At the very least, it'll make sure const-ness and reference-ness is preserved by ExecuteMethod(), and it's a lot cleaner than my old ideas.
See here.
There are further improvements that can be made, however. As I'm out of space, see here.
Notes:
int16_t (a.k.a. std::int16_t) is in the header <cstdint>.
std::true_type and std::false_type are in the header <type_traits>.
It's difficult to tell from your description, but this is my closest interpretation to what you asked:
auto foo(int) { cout << "foo int" << endl; }
auto foo(float) { cout << "foo float" << endl; }
//... other foo overloads...
template <class T>
auto uber_function(T t)
{
foo(t);
}
template <class T, class... Args>
auto uber_function(T t, Args... args)
{
foo(t);
uber_function(args...);
}
auto main() -> int
{
uber_function(3, 2.4f);
return 0;
}
Of course this can be improved to take references, to make forwarding. This is just for you to have a starting point. As you weren't more clear, I can't give a more specific answer.

Check at Compile-Time if Template Argument is void

I'm trying to wrap the Windows API functions to check errors when I so choose. As I found out in a previous SO question, I could use a template function to call the API function, and then call GetLastError() to retrieve any error it might have set. I could then pass this error to my Error class to let me know about it.
Here's the code for the template function:
template<typename TRet, typename... TArgs>
TRet Wrap(TRet(WINAPI *api)(TArgs...), TArgs... args)
{
TRet ret = api(args...);
//check for errors
return ret;
}
Using this I can have code as follows
int WINAPI someFunc (int param1, BOOL param2); //body not accessible
int main()
{
int ret = someFunc (5, true); //works normally
int ret2 = Wrap (someFunc, 5, true); //same as above, but I'll get a message if there's an error
}
This works wonderfully. However, there is one possible problem. Take the function
void WINAPI someFunc();
When subbing this into the template function, it looks as follows:
void Wrap(void(WINAPI *api)())
{
void ret = api(); //<-- ahem! Can't declare a variable of type void...
//check for errors
return ret; //<-- Can't return a value for void either
}
To get around this, I tried creating a version of the template where I replaced TRet with void. Unfortunately, this actually just causes an ambiguity of which one to use.
That aside, I tried using
if (strcmp (typeid (TRet).name(), "v") != 0) //typeid(void).name() == "v"
{
//do stuff with variable to return
}
else
{
//do stuff without returning anything
}
However, typeid is a runtime comparison, so the code still doesn't compile due to trying to declare a void variable, even if it never will.
Next, I tried using std::is_same <TRet, void>::value instead of typeid, but found out that it was a runtime comparison as well.
At this point, I don't know what to try next. Is there any possibility of getting the compiler to believe that I know what I'm doing will run fine? I don't mind attaching an extra argument to Wrap, but I couldn't really get anything out of that either.
I use Code::Blocks with GNU G++ 4.6.1, and Windows XP, as well as Windows 7. Thanks for any help, even if it is telling me that I'll have to end up just not using Wrap for functions that return void.
You can use a helper class to fine tune specializations:
template <typename F>
struct wrapper
{};
template <typename Res, typename... Args>
struct wrapper<Res(Args...)>
{
static Res wrap(Res (WINAPI *f)(Args...), Args&& args...)
{
Res r = f(std::forward<Args>(args)...);
// Blah blah
return r;
}
};
template <typename... Args>
struct wrapper<void(Args...)>
{
static void wrap(void (WINAPI *f)(Args...), Args&& args...)
{
f(std::forward<Args>(args)...);
// Blah blah
}
};
Now, you can write the wrapper:
template <typename Res, typename... Args>
Res Wrap(Res (WINAPI *f)(Args...), Args&& args...)
{
return wrapper<Res(Args...)>::wrap(f, std::forward<Args>(args)...);
}
Note that it works even when Res is void. You're allowed to return an expression returning void in a function returning void.
The correct type is deduced, as in Wrap(someFunc, 5, true), even for functions returning void.
To get around this, I tried creating a version of the template where I replaced TRet with void. Unfortunately, this actually just causes an ambiguity of which one to use.
That should work, I believe, because void is more specialised than TRet, but as you point out it doesn't. I may be missing something, but at any rate, it doesn't matter, you can prevent the TRet overload from being selected.
template<typename TFun, typename... TArgs>
auto Wrap(TFun api, TArgs&&... args) ->
typename std::enable_if<
!std::is_void<typename std::result_of<TFun(TArgs...)>::type>::value,
typename std::result_of<TFun(TArgs...)>::type
>::type
{
auto result = api(std::forward<TArgs&&>(args)...);
return result;
}
template<typename TFun, typename... TArgs>
auto Wrap(TFun api, TArgs&&... args) ->
typename std::enable_if<
std::is_void<typename std::result_of<TFun(TArgs...)>::type>::value,
typename std::result_of<TFun(TArgs...)>::type
>::type
{
api(std::forward<TArgs&&>(args)...);
}
void WINAPI f1()
{
}
void WINAPI f2(double)
{
}
int WINAPI f3()
{
return 0;
}
int WINAPI f4(double)
{
return 0;
}
int main() {
Wrap(f1);
Wrap(f2, 0);
return Wrap(f3) * Wrap(f4, 0);
}
Update: adjusted to allow for conversions from argument type to parameter type.
Promoting from comment to answer I understanding why specializing the return type as void didn't work (can't disambiguate on return types) but specializing with void and adding an additional parameter should work, what happened? You may have to invoke with explicit types.

How can I iterate over a packed variadic template argument list?

I'm trying to find a method to iterate over an a pack variadic template argument list.
Now as with all iterations, you need some sort of method of knowing how many arguments are in the packed list, and more importantly how to individually get data from a packed argument list.
The general idea is to iterate over the list, store all data of type int into a vector, store all data of type char* into a vector, and store all data of type float, into a vector. During this process there also needs to be a seperate vector that stores individual chars of what order the arguments went in. As an example, when you push_back(a_float), you're also doing a push_back('f') which is simply storing an individual char to know the order of the data. I could also use a std::string here and simply use +=. The vector was just used as an example.
Now the way the thing is designed is the function itself is constructed using a macro, despite the evil intentions, it's required, as this is an experiment. So it's literally impossible to use a recursive call, since the actual implementation that will house all this will be expanded at compile time; and you cannot recruse a macro.
Despite all possible attempts, I'm still stuck at figuring out how to actually do this. So instead I'm using a more convoluted method that involves constructing a type, and passing that type into the varadic template, expanding it inside a vector and then simply iterating that. However I do not want to have to call the function like:
foo(arg(1), arg(2.0f), arg("three");
So the real question is how can I do without such? To give you guys a better understanding of what the code is actually doing, I've pasted the optimistic approach that I'm currently using.
struct any {
void do_i(int e) { INT = e; }
void do_f(float e) { FLOAT = e; }
void do_s(char* e) { STRING = e; }
int INT;
float FLOAT;
char *STRING;
};
template<typename T> struct get { T operator()(const any& t) { return T(); } };
template<> struct get<int> { int operator()(const any& t) { return t.INT; } };
template<> struct get<float> { float operator()(const any& t) { return t.FLOAT; } };
template<> struct get<char*> { char* operator()(const any& t) { return t.STRING; } };
#define def(name) \
template<typename... T> \
auto name (T... argv) -> any { \
std::initializer_list<any> argin = { argv... }; \
std::vector<any> args = argin;
#define get(name,T) get<T>()(args[name])
#define end }
any arg(int a) { any arg; arg.INT = a; return arg; }
any arg(float f) { any arg; arg.FLOAT = f; return arg; }
any arg(char* s) { any arg; arg.STRING = s; return arg; }
I know this is nasty, however it's a pure experiment, and will not be used in production code. It's purely an idea. It could probably be done a better way. But an example of how you would use this system:
def(foo)
int data = get(0, int);
std::cout << data << std::endl;
end
looks a lot like python. it works too, but the only problem is how you call this function.
Heres a quick example:
foo(arg(1000));
I'm required to construct a new any type, which is highly aesthetic, but thats not to say those macros are not either. Aside the point, I just want to the option of doing:
foo(1000);
I know it can be done, I just need some sort of iteration method, or more importantly some std::get method for packed variadic template argument lists. Which I'm sure can be done.
Also to note, I'm well aware that this is not exactly type friendly, as I'm only supporting int,float,char* and thats okay with me. I'm not requiring anything else, and I'll add checks to use type_traits to validate that the arguments passed are indeed the correct ones to produce a compile time error if data is incorrect. This is purely not an issue. I also don't need support for anything other then these POD types.
It would be highly apprecaited if I could get some constructive help, opposed to arguments about my purely illogical and stupid use of macros and POD only types. I'm well aware of how fragile and broken the code is. This is merley an experiment, and I can later rectify issues with non-POD data, and make it more type-safe and useable.
Thanks for your undertstanding, and I'm looking forward to help.
If your inputs are all of the same type, see OMGtechy's great answer.
For mixed-types we can use fold expressions (introduced in c++17) with a callable (in this case, a lambda):
#include <iostream>
template <class ... Ts>
void Foo (Ts && ... inputs)
{
int i = 0;
([&]
{
// Do things in your "loop" lambda
++i;
std::cout << "input " << i << " = " << inputs << std::endl;
} (), ...);
}
int main ()
{
Foo(2, 3, 4u, (int64_t) 9, 'a', 2.3);
}
Live demo
(Thanks to glades for pointing out in the comments that I didn't need to explicitly pass inputs to the lambda. This made it a lot neater.)
If you need return/breaks in your loop, here are some workarounds:
Demo using try/throw. Note that throws can cause tremendous slow down of this function; so only use this option if speed isn't important, or the break/returns are genuinely exceptional.
Demo using variable/if switches.
These latter answers are honestly a code smell, but shows it's general-purpose.
If you want to wrap arguments to any, you can use the following setup. I also made the any class a bit more usable, although it isn't technically an any class.
#include <vector>
#include <iostream>
struct any {
enum type {Int, Float, String};
any(int e) { m_data.INT = e; m_type = Int;}
any(float e) { m_data.FLOAT = e; m_type = Float;}
any(char* e) { m_data.STRING = e; m_type = String;}
type get_type() const { return m_type; }
int get_int() const { return m_data.INT; }
float get_float() const { return m_data.FLOAT; }
char* get_string() const { return m_data.STRING; }
private:
type m_type;
union {
int INT;
float FLOAT;
char *STRING;
} m_data;
};
template <class ...Args>
void foo_imp(const Args&... args)
{
std::vector<any> vec = {args...};
for (unsigned i = 0; i < vec.size(); ++i) {
switch (vec[i].get_type()) {
case any::Int: std::cout << vec[i].get_int() << '\n'; break;
case any::Float: std::cout << vec[i].get_float() << '\n'; break;
case any::String: std::cout << vec[i].get_string() << '\n'; break;
}
}
}
template <class ...Args>
void foo(Args... args)
{
foo_imp(any(args)...); //pass each arg to any constructor, and call foo_imp with resulting any objects
}
int main()
{
char s[] = "Hello";
foo(1, 3.4f, s);
}
It is however possible to write functions to access the nth argument in a variadic template function and to apply a function to each argument, which might be a better way of doing whatever you want to achieve.
Range based for loops are wonderful:
#include <iostream>
#include <any>
template <typename... Things>
void printVariadic(Things... things) {
for(const auto p : {things...}) {
std::cout << p.type().name() << std::endl;
}
}
int main() {
printVariadic(std::any(42), std::any('?'), std::any("C++"));
}
For me, this produces the output:
i
c
PKc
Here's an example without std::any, which might be easier to understand for those not familiar with std::type_info:
#include <iostream>
template <typename... Things>
void printVariadic(Things... things) {
for(const auto p : {things...}) {
std::cout << p << std::endl;
}
}
int main() {
printVariadic(1, 2, 3);
}
As you might expect, this produces:
1
2
3
You can create a container of it by initializing it with your parameter pack between {}. As long as the type of params... is homogeneous or at least convertable to the element type of your container, it will work. (tested with g++ 4.6.1)
#include <array>
template <class... Params>
void f(Params... params) {
std::array<int, sizeof...(params)> list = {params...};
}
This is not how one would typically use Variadic templates, not at all.
Iterations over a variadic pack is not possible, as per the language rules, so you need to turn toward recursion.
class Stock
{
public:
bool isInt(size_t i) { return _indexes.at(i).first == Int; }
int getInt(size_t i) { assert(isInt(i)); return _ints.at(_indexes.at(i).second); }
// push (a)
template <typename... Args>
void push(int i, Args... args) {
_indexes.push_back(std::make_pair(Int, _ints.size()));
_ints.push_back(i);
this->push(args...);
}
// push (b)
template <typename... Args>
void push(float f, Args... args) {
_indexes.push_back(std::make_pair(Float, _floats.size()));
_floats.push_back(f);
this->push(args...);
}
private:
// push (c)
void push() {}
enum Type { Int, Float; };
typedef size_t Index;
std::vector<std::pair<Type,Index>> _indexes;
std::vector<int> _ints;
std::vector<float> _floats;
};
Example (in action), suppose we have Stock stock;:
stock.push(1, 3.2f, 4, 5, 4.2f); is resolved to (a) as the first argument is an int
this->push(args...) is expanded to this->push(3.2f, 4, 5, 4.2f);, which is resolved to (b) as the first argument is a float
this->push(args...) is expanded to this->push(4, 5, 4.2f);, which is resolved to (a) as the first argument is an int
this->push(args...) is expanded to this->push(5, 4.2f);, which is resolved to (a) as the first argument is an int
this->push(args...) is expanded to this->push(4.2f);, which is resolved to (b) as the first argument is a float
this->push(args...) is expanded to this->push();, which is resolved to (c) as there is no argument, thus ending the recursion
Thus:
Adding another type to handle is as simple as adding another overload, changing the first type (for example, std::string const&)
If a completely different type is passed (say Foo), then no overload can be selected, resulting in a compile-time error.
One caveat: Automatic conversion means a double would select overload (b) and a short would select overload (a). If this is not desired, then SFINAE need be introduced which makes the method slightly more complicated (well, their signatures at least), example:
template <typename T, typename... Args>
typename std::enable_if<is_int<T>::value>::type push(T i, Args... args);
Where is_int would be something like:
template <typename T> struct is_int { static bool constexpr value = false; };
template <> struct is_int<int> { static bool constexpr value = true; };
Another alternative, though, would be to consider a variant type. For example:
typedef boost::variant<int, float, std::string> Variant;
It exists already, with all utilities, it can be stored in a vector, copied, etc... and seems really much like what you need, even though it does not use Variadic Templates.
There is no specific feature for it right now but there are some workarounds you can use.
Using initialization list
One workaround uses the fact, that subexpressions of initialization lists are evaluated in order. int a[] = {get1(), get2()} will execute get1 before executing get2. Maybe fold expressions will come handy for similar techniques in the future. To call do() on every argument, you can do something like this:
template <class... Args>
void doSomething(Args... args) {
int x[] = {args.do()...};
}
However, this will only work when do() is returning an int. You can use the comma operator to support operations which do not return a proper value.
template <class... Args>
void doSomething(Args... args) {
int x[] = {(args.do(), 0)...};
}
To do more complex things, you can put them in another function:
template <class Arg>
void process(Arg arg, int &someOtherData) {
// You can do something with arg here.
}
template <class... Args>
void doSomething(Args... args) {
int someOtherData;
int x[] = {(process(args, someOtherData), 0)...};
}
Note that with generic lambdas (C++14), you can define a function to do this boilerplate for you.
template <class F, class... Args>
void do_for(F f, Args... args) {
int x[] = {(f(args), 0)...};
}
template <class... Args>
void doSomething(Args... args) {
do_for([&](auto arg) {
// You can do something with arg here.
}, args...);
}
Using recursion
Another possibility is to use recursion. Here is a small example that defines a similar function do_for as above.
template <class F, class First, class... Rest>
void do_for(F f, First first, Rest... rest) {
f(first);
do_for(f, rest...);
}
template <class F>
void do_for(F f) {
// Parameter pack is empty.
}
template <class... Args>
void doSomething(Args... args) {
do_for([&](auto arg) {
// You can do something with arg here.
}, args...);
}
You can't iterate, but you can recurse over the list. Check the printf() example on wikipedia: http://en.wikipedia.org/wiki/C++0x#Variadic_templates
You can use multiple variadic templates, this is a bit messy, but it works and is easy to understand.
You simply have a function with the variadic template like so:
template <typename ...ArgsType >
void function(ArgsType... Args){
helperFunction(Args...);
}
And a helper function like so:
void helperFunction() {}
template <typename T, typename ...ArgsType >
void helperFunction(T t, ArgsType... Args) {
//do what you want with t
function(Args...);
}
Now when you call "function" the "helperFunction" will be called and isolate the first passed parameter from the rest, this variable can b used to call another function (or something). Then "function" will be called again and again until there are no more variables left. Note you might have to declare helperClass before "function".
The final code will look like this:
void helperFunction();
template <typename T, typename ...ArgsType >
void helperFunction(T t, ArgsType... Args);
template <typename ...ArgsType >
void function(ArgsType... Args){
helperFunction(Args...);
}
void helperFunction() {}
template <typename T, typename ...ArgsType >
void helperFunction(T t, ArgsType... Args) {
//do what you want with t
function(Args...);
}
The code is not tested.
#include <iostream>
template <typename Fun>
void iteratePack(const Fun&) {}
template <typename Fun, typename Arg, typename ... Args>
void iteratePack(const Fun &fun, Arg &&arg, Args&& ... args)
{
fun(std::forward<Arg>(arg));
iteratePack(fun, std::forward<Args>(args)...);
}
template <typename ... Args>
void test(const Args& ... args)
{
iteratePack([&](auto &arg)
{
std::cout << arg << std::endl;
},
args...);
}
int main()
{
test(20, "hello", 40);
return 0;
}
Output:
20
hello
40