Welcome, this is very rare use-case question.
So, here is what I'm trying to do - lets say I have a variadic template function which takes T ...args and a function type FuncT funcName, so here is what we have so far:
template<typename FuncT, typename ...T>
void myFunction(FuncT (*funcName), T ...args);
Now, I want to store my function at void (*)() (this store functions). This works just fine.
std::deque<void (*)()> functions;
func = functions.front();
func(std::forward<T>(args)...); //args is vardict template argument
Now, I can just pass a function to my function as in:
template<typename FuncT, typename T>
int sharedArgument;
void setArg(int x){
sharedArgument = x;
}
template<typename FuncT>
void myFunction(FuncT funcName){
funcName(sharedArgument);
}
void function(int i){
std::cout << i;
}
int main(){
setArg(5);
myFunction(function);
}
Now, I know this is unnecesary, but i want to present a more complicated problem that im having trouble with.
When i want to store arguemnts, I will probably use std::tuple, its design to store arguments, but
Main question is:
How do i store variable amount of arguments in tuple and then perfectly forward them as normal arguments to some function, so that function receiving
function(std::tupleArgumentsHere...);
will read it as
function(5, 42, "yes", 3.14);
I will use this to store arguments and pass them to std::thread.
Thank you, Cheers.
Use std::apply. It is new in c++17. If you cannot, write your own.
In c++14, make an index sequence the same length as your tuple. Then func(std::get<Is>(std::forward<Tup>(tup))...).
In c++11 do the same thing but write your own index sequence.
std::bind stores the function and the arguments together. It returns a callable object encapsulating a copy of the argument values.
You can also use its "placeholder" facility in case there are additional arguments to add after calling queue.front().
Related
I have a function pointer that I need to pass to a function that expects a std::function. The function that takes the std::function is templated and uses the std::function's arguments to deduce a parameter pack, meaning an implicit conversion won't work.
I could construct the std::function myself, but the function being passed has many arguments, and writing them into the template brackets of std::function will not be sustainable, as I need to do this often with many similar functions that I pass to this function.
Is there a way to convert a function pointer to a std::function without specifying the return type and arguments, by some form of deducing?
This is what I've tried so far:
template <auto* F>
struct stdfunc {};
template <class Ret, class... Args, auto (*F)(Args...) -> Ret>
struct stdfunc<F>
{
typedef std::function<Ret(Args...)> type;
};
The above code does not work as intended. I found the syntax in this answer. In that case, it wasn't used for this purpose, but surely there is a way to achieve what I'm trying to do using this technique? It seems like all the pieces are there, I just have to put them in the right place.
Am I on the right track?
I suggest:
template<typename Func>
auto make_function(Func ptr)
{
return std::function<std::remove_pointer_t<Func>>(ptr);
}
and then simply pass "make_function(my_func)".
(Thanks toRemy Lebeau for suggesting use of "auto")
I have the following function
template <typename... Args>
void func(Args&&... args){
// do stuff
}
I now want to create a function pointer, that is callable with a variadic list of arguments, just like the function itself.
template <typename... Args>
using Var_Func = void(*)(Args... args)
At this point, I'm stuck. When creating a variable of type Var_Func, I have to give a list of types for the template:
Var_Func<[List of types]> var_func_p = &func;
This, however, prevents me from calling the pointer with a true variadic list of arguments. I want a pointer, that allows me to call it like a true variadic function, like this:
var_func_p("Test");
var_func_p(0.3, 5);
var_func_p('c', "Another test", 1.3, 3);
I have no idea how to achieve this. Can someone help me?
func isn't actually a function. It's a template that the compiler can use to create new functions when it needs to.
When you do func(5) the compiler creates a function called func<int> and then calls it. When you do func(5.0, 'a') the compiler creates a function called func<double, char> and then calls it. These are two completely different, unrelated functions with two different types.
You can create a pointer to func<int> or func<double, char> or func<> or func<anything else> in the usual way. But you cannot ever create a pointer to func, because func is not a function, it's an instruction for the compiler.
Simply put, this is not possible.
A function template is not a function, it's a template of a function -- and thus it does not have a function pointer until you specify which instantiation you want. At which point, the pointer is fixed to a specific number of arguments of specific types.
It is not possible in the C++ language to type-erase templates into a singular type, such as a pointer that you can pass around and lazily instantiate.
That is, code such as:
some_discrete_variadic_type x = var_func_1;
x(1);
x(1, "2");
x = var_func_2;
x(1);
x(1, "2");
Is not possible, because for type-erasure to work you must normalize the erasure to a fixed number of types (in this case, it would be instantiations).
Depending on what the problem is you are trying to solve, however, there might be workarounds -- though this would require more information.
If your uses are more limited -- such as to pass the functionality into other functions that are only ever known at compile-time, then you can use Functor objects instead and pass them into function templates where the arguments are deduced. For example:
struct var_func
{
template <typename...Args>
auto operator()(Args&&...args) -> void
{
// do something
}
};
Where an example of it being called could be:
template <typename T>
auto consume(T var_func_p) -> void
{
var_func_p("Test");
var_func_p(0.3, 5);
var_func_p('c', "Another test", 1.3, 3);
}
int main()
{
consume(var_func{});
consume(some_other_var_func{});
}
Note that in this case, you're not passing a function template around anymore. You're passing a static object, var_func, which contains a call-operator (operator()) that is a function template.
Like this:
template <typename... Args>
void func(Args&&... args){
// do stuff
}
template <typename... Args>
using f_ptr = void(*)(Args&&...);
int main() {
f_ptr<int,int> p = &func<int,int>;
p(3,1);
}
However, pointers to different instantations of func are incompatible.
This, however, prevents me to call the pointer with a true variadic list of arguments. I want a pointer, that allows me to call it like a true variadic function, like this:
You cannot store a pointer to eg func<double,double> in a f_ptr<int,int>.
My situation
I have two classes, supplied by an external libary not under my control, e.g. their interface is fixed for me.
The first one is a templated 2-D container type, that allows me to manipulate the content held through member functions as well as through raw pointer.
The second one is a class containing a bunch of static member functions that abstract some heavily SIMD-optimized vector operations. Most of them are overloaded to take different datatypes, however they all share a same interface like
VecOperations::op (Type* dest, const Type* src, /* a variable number of operation specific arguments */, int len)
What I want to achieve:
I want to iterate over the first dimension of my 2D container and apply a vector operation to each vector in the second iteration in place. Therefore I want to replace e.g.
auto** ptrs = conatiner.getArrayOfRawPointers();
for (int i = 0; i < container.getXDim(); ++i)
VecOperations::foo (ptrs[i], ptrs[i], arg1, arg2, arg3, container.getYDim());
ideally by something like this (pseudocode)
forAllElements<VecOperations::foo> (container, arg1, arg2, arg3);
This should work for all kind of types stored in my container which are supported by the vector operations classes well as for all numbers of vector operation specific args. To my knowledge writing something like forAllElements above is not possible.
My current solution:
I came up with this instead:
template <typename ElemType, typename ...Args>
struct ForAllElemements
{
template <void(*op)(ElemType*, const ElemType*, Args..., int)>
static void call (Container<ElemType>& buffer, Args... args)
{
auto xDim = container.getXDim();
auto yDim = container.getYDim();
auto** ptrs = conatiner.getArrayOfRawPointers();
for (int i = 0; i < xDim; ++i)
op (ptrs[i], const_cast<const ElemType*>(ptrs[i]), args..., yDim);
}
};
This can be used like
// using a Container<float> and VecOperations::foo (float*, const float*, float, int, float, int)
ForAllElemements<float, float, int, float>::call<VecOperations::foo> (container, arg1, arg2, arg3);
While in C++17 deducing class template arguments from the constructor works, deducing it from a static function call does not work to my knowledge. From my understanding, this is simply not defined, technically I don't see any reason why
ForAllElemements::call<VecOperations::foo> (container, arg1, arg2, arg3);
should be impossible, as all template types can be deduced from the parameters passed to the static function.
So I'm asking you, is there any super clever workaround or pattern I'm not aware of that would make something like this possible with C++17 or also with the later standards?
Class template argument deduction happens only based on an initializer for a class object. Here you don't even want an object of the class type, just to use static member functions.
But backing up, maybe a plain function template can work:
// C++20 will define std::type_identity_t; or just define your own:
template <typename T>
struct type_identity { using type = T; };
template <typename T>
using type_identity_t = typename type_identity<T>::type;
template <typename ...Args, typename ElemType>
void forAllElements(
Container<ElemType> &c,
void (*op)(ElemType*, const ElemType*, type_identity_t<Args>..., int),
Args...);
The function pointer does need to be a function argument here instead of a template argument. This works with plain Args... in the function pointer signature instead of type_identity_t<Args>... if the function is overloaded, but when the function is NOT overloaded, compilers might require the type_identity_t, presumably to make sure Args is in a non-deduced context there. (I think there's an unclear requirement in the Standard causing some different results...)
Note Args can only be deduced from the arguments to forAllElements and not from the function type, and the function type needs to be an exact match. So if you allow those types to be deduced, you'll need to be careful about the exact types of the expressions you pass in. Cast them if necessary. If using literals as constant values, you can use forms like 1.0f to get a float type, etc. Or, you can specify the argument types like forAllElements<float, int, float>, which is why I put ...Args before ElemType in the template (though now ElemType can never be explicitly given and must be deduced from the container argument).
I'd like to be able to infer the first argument of a callable. I can make it work for free and member functions, but I'm struggling with lambdas. Is there some trick I can use?
Here's an example. Within the match functions below, I want to use the knowledge of T.
template<class T>
void match(void (*)(T*, int)) { /* First */ }
template<class T>
void match(void (T::*)(int)) { /* Second */ }
template<class T>
void match(std::function<void(T,int)>) { /* Third */ }
struct A
{
void f(int) {}
};
void g(A*, int) {}
match(&A::f); // Ok, matches first
match(&g); // Ok, matches second
match([](A*, int) {}); // Not Ok
match([&](A*, int) {}); // Not Ok
You cannot.
template<class T>
void g(T*, int) {}
fails to work
void g(void*, int) {}
void g(std::string**, int) {}
fails to work.
The same problem holds with lambdas.
As a general rule, you can ask "can I invoke X with type Y", you cannot get the signature.
std::function is not a lambda, and a lambda is not a std::function. They are unrelated types, other than the fact you can convert a lambda to a std::function with any compatible signature, just like you can convert any callable object.
If you restrict your problem space enough, you could write a traits class to extract the signature of operator() on the incoming object, and treat that as the arguments to a lambda.
This is a bad idea in C++11, and it generally gets worse in C++14 and C++17. [](auto a, int b){} is a lambda in C++14 (and many C++11 compilers support it), and it has no fixed type for the first argument.
Usually a better approach is to bundle the signature up separately than the callable. This violates DRY (Don't Repeat Yourself) in C++11, but in C++14 the lambda can just take auto&& parameters.
Another approach is to ask the question "which of these types work", which can be done. Usually you don't have an unlimited family of types you are working with, but rather an enumerated set.
I know only a way: pass through a std::function
match(std::function<void(A*, int)>([](A*, int) {}));
match(static_cast<std::function<void(A*, int)>>([&](A*, int) {}));
A function named test takes std::function<> as its parameter.
template<typename R, typename ...A>
void test(std::function<R(A...)> f)
{
// ...
}
But, if I do the following:
void foo(int n) { /* ... */ }
// ...
test(foo);
Compiler(gcc 4.6.1) says no matching function for call to test(void (&)(int)).
To make the last line test(foo) compiles and works properly, how can I modify the test() function? In test() function, I need f with type of std::function<>.
I mean, is there any template tricks to let compiler determine the signature of function(foo in example), and convert it to std::function<void(int)> automatically?
EDIT
I want to make this work for lambdas (both stateful and stateless) as well.
It looks like you want to use overloading
template<typename R, typename ...A>
void test(R f(A...))
{
test(std::function<R(A...)>(f));
}
This simple implementation will accept most if not all the functions you will try to pass. Exotic functions will be rejected (like void(int...)). More work will give you more genericity.
std::function implements the Callable interface, i.e. it looks like a function, but that doesn't mean you should require callable objects to be std::functions.
template< typename F > // accept any type
void test(F const &f) {
typedef std::result_of< F( args ) >::type R; // inspect with traits queries
}
Duck typing is the best policy in template metaprogramming. When accepting a template argument, be unspecific and just let the client implement the interface.
If you really need a std::function for example to re-target the variable or something crazy like that, and you know the input is a raw function pointer, you can decompose a raw function pointer type and reconsitute it into a std::function.
template< typename R, typename ... A >
void test( R (*f)( A ... ) ) {
std::function< R( A ... ) > internal( f );
}
Now the user can't pass a std::function because that has been encapsulated within the function. You could keep your existing code as another overload and just delegate to that, but be careful to keep interfaces simple.
As for stateful lambdas, I don't know how to handle that case. They don't decompose to function pointers and as far as I know the argument types cannot be queried or deduced. This information is necessary to instantiate std::function, for better or worse.
This is an old one, and I can't seem to find much on the same topic, so I thought I would go ahead and put in a note.
Compiled on GCC 4.8.2, the following works:
template<typename R, typename... A>
R test(const std::function<R(A...)>& func)
{
// ...
}
However, you can't just call it by passing in your pointers, lambdas, etc. However, the following 2 examples both work with it:
test(std::function<void(int, float, std::string)>(
[](int i, float f, std::string s)
{
std::cout << i << " " << f << " " << s << std::endl;
}));
Also:
void test2(int i, float f, std::string s)
{
std::cout << i << " " << f << " " << s << std::endl;
}
// In a function somewhere:
test(std::function<void(int, float, std::string)>(&test2));
The downside of these should stand out pretty obviously: you have to explicitly declare the std::function for them, which might look a little bit ugly.
That said, though, I threw that together with a tuple that gets expanded to call the incoming function, and it works, just requiring a little bit more of an explicitly saying what you're doing calling the test function.
Example code including the tuple thing, if you want to play with it: http://ideone.com/33mqZA
It's usually ill-advised to accept std::function by value unless you are at 'binary delimitation' (e.g. dynamic library, 'opaque' API) since as you've just witnessed they play havoc with overloading. When a function does in fact take an std::function by value then it's often the burden of the caller to construct the object to avoid the overloading problems (if the function is overloaded at all).
Since however you've written a template, it's likely the case that you're not using std::function (as a parameter type) for the benefits of type-erasure. If what you want to do is inspecting arbitrary functors then you need some traits for that. E.g. Boost.FunctionTypes has traits such as result_type and parameter_types. A minimal, functional example:
#include <functional>
#include <boost/function_types/result_type.hpp>
#include <boost/function_types/parameter_types.hpp>
#include <boost/function_types/function_type.hpp>
template<typename Functor>
void test(Functor functor) // accept arbitrary functor!
{
namespace ft = boost::function_types;
typedef typename ft::result_type<Functor>::type result_type;
typedef ft::parameter_types<Functor> parameter_types;
typedef typename boost::mpl::push_front<
parameter_types
, result_type
>::type sequence_type;
// sequence_type is now a Boost.MPL sequence in the style of
// mpl::vector<int, double, long> if the signature of the
// analyzed functor were int(double, long)
// We now build a function type out of the MPL sequence
typedef typename ft::function_type<sequence_type>::type function_type;
std::function<function_type> function = std::move(functor);
}
As a final note, I do not recommend introspecting functors (i.e. prodding for their result type and argument types) in the general case as that simply don't work for polymorphic functors. Consider several overloaded operator(): then there is no 'canonical' result type or argument types. With C++11 it's better to 'eagerly' accept any kind of functor, or constrain them using techniques like SFINAE or static_assert depending on the needs, and later on (when parameters are available) to use std::result_of to inspect the result type for a given set of arguments. A case where constraining up front is desirable is when the aim is to store functors into e.g. a container of std::function<Sig>.
To get a taste of what I mean by the previous paragraph it's enough to test the above snippet with polymorphic functors.