C++ std::function-like template syntax - templates

In C++11 you can instantiate std::function like this:
std::function<void(int)> f1;
std::function<int(std::string, std::string)> f2;
//and so on
But while there is plenty of info on variadic templates on the web, I fail to find any articles on how to write std::function-like template which would accept parenthesized arguments.
Could anyone please explain the syntax and its limitations or at least point to an existing explanation?

There's nothing special about it, it's an ordinary function type. When you declare a function like this:
int foo(char a, double b)
Then its type is int (char, double). One way of "unwrapping" the individual argument types and return type is to use partial template specialisation. Basically, std::function looks something like this:
template <class T>
struct function; // not defined
template <class R, class... A>
struct function<R (A...)>
{
// definition here
};

Pretty much like any other template, since int(std::string, std::string) is just a type.
Here's a really naive example that compiles:
template <typename FType>
struct Functor
{
Functor(FType* fptr) : fptr(fptr) {}
template <typename ...Args>
void call(Args... args)
{
fptr(args...);
}
private:
FType* fptr;
};
void foo(int x, char y, bool z) {}
int main()
{
Functor<void(int, char, bool)> f(&foo);
f.call(1, 'a', true);
//f.call(); // error: too few arguments to function
}
In reality you'd have a specialisation on FType being ReturnType(ArgTypes...), though my naive example will already give you the validation you need if you try to invoke it in in compatible ways.

Related

c++ parameter pack specification in constructor rather than template

Unlike function declarations with parameter packs, I've found that classes require the type for each argument in the angle brackets...
Component<IntegerPair, int, int> temp(40, 5);
...which seems redundant. Here's how I defined Component:
template<typename T, class... T_Args>
class Component
{
public:
Component(T_Args... args)
: m_data(args...)
{}
T m_data;
};
Is there a way to remove int, int from the above statement?
If so, is it ok to remove it?
Also, is my way of instantiation m_data safe? When using
std::forward<T_Args>(args)... my compiler told me I didn't have a
constructor that could convert all of the argument types.
One way is to make the constructor a template:
#include <utility>
struct IntegerPair {
IntegerPair(int, int) {}
};
template<typename T>
class Component
{
public:
template<typename... T_Args>
Component(T_Args&&... args)
: m_data(std::forward<T_Args>(args)...)
{}
T m_data;
};
int main()
{
Component<IntegerPair> c {1,2};
}
This is functionally equivalent to std::vector and its member function emplace_back. It's perfectly ok, IMO. The error messages are pretty cryptic, as usual in template constructs like this, but this can be mitigated with an appropriate static_assert.
template parameter deduction only work for function calls so the basic pattern to achieve what you want looks like this:
template<typename T, class... T_Args>
Component<T, T_Args...> makeComponent(T_Args&&... args) {
return Component<T, T_Args...>(std::forward<T_Args>(args)...);
}
Usage:
auto c = makeComponent<IntegerPair>(1, 1)

How to make a call to a template function less verbose

There is a function
template <class ...T>
void foo(std::function<void(T...)> callback);
into which I pass a callback.
I'd like to do something like
foo(bar);
where bar is, for example,
void bar(int a, long b, double c, float d);
but that gives me
error: no matching function for call to bar(void (&)(int, long int, double, float))
I have to call foo as
foo(std::function<void(int, long, double, float)>(bar));
which is too verbose. Even
foo<int, long, double, float>(bar);
would have been better.
foo(bar);
would be just ideal.
Anyway, how can I make calls to foo to be less verbose?
Edit: declaration of foo has to stay the same.
I'd write a wrapper function that translates the function pointer into a std::function wrapper:
template <typename... T>
void foo(std::function<void (T...)> f) {}
template <typename... T>
void foo(void (*f)(T...)) {
foo(std::function<void (T...)>(f));
}
foo() can then be called either way:
void bar(int,double) {}
void foo_caller() {
foo(std::function<void (int,double)>(bar));
foo(bar);
}
Addendum: Non-static member function wrapper
Same approach can be used for pointer-to-member functions — just add another overload:
template <typename C,typename... T>
void foo(void (C::*f)(T...)) {
foo(std::function<void (C *,T...)>(f));
}
Note the extra first parameter for the this pointer for the member function. Usage is similar:
struct quux {
void mf(char *,double) {}
};
void foo_caller() {
foo(&quux::mf);
}
If you know you will pass a plain function pointer to foo, and not just any C++11 lambda, you can redefine foo as:
template <class ...T>
void foo(void(*callback)(T...)) {
// .....
}
If you want to support lambdas, you can be more generic with the type
template <class LambdaType>
void foo(LambdaType callback) {
// .....
}
the downside of this approach is that if you pass something that is not a function or lambda, you will get weird template error messages coming from inside of foo.
With your original solution the compiler has problems matching T... to int, long, double, float, probably because it is a nested type.
If I told you to match void(int, double) to MyTempalte<T...> you wouldn't know that I intend to replace T... with int, double, because you don't know what MyTemplate does with its arguments. Maybe MyTemplate is doing something weird to its template arguments first?
Same, the compiler doesn't know how to match std::function template parameters to your function pointer.
In case your foo definition is not set in stone, can change it to
#include <functional>
template <class Ret, class ...T>
void foo(Ret callback(T... params))
{
}
void bar(int a, long b, double c, float d){}
int main()
{
foo(bar);
}

avoid specifying redundant template parameters which contain templated function pointer

Suppose we have this code:
template <class T, void (*u)(T&)>
void Foo()
{
// store the function u internally . . .
}
There are reasons to do something like this and I won't attempt to go into them. However, is there any way to avoid having to specify type T when calling Foo()? For example, to compile, one normally needs:
Foo<int, MyIntFunction>();
But if this int can be deduced from the function pointer, is this possible:
Foo<MyIntFunction>();
EDIT I'm aware of the solution to pass the actual function pointer in as a function parameter, however this is not desired here as it has some perf drawbacks in intensive loop.
In this example u is not a function pointer, it's a type (the signature of a function pointer). If you want to store a function pointer you need to pass it.
template<class T, class F = void(*)(T&)>
void Foo(F f)
{
// store the function pointer f here
}
called like so:
struct SomeType {};
void bar(SomeType& x);
Foo(&bar);
Is this what you mean to do?
Short answer: I don't think it is possible.
Long one.. When calling a template function, you cannot omit the first parameter and specify the second: the compiler would try to match your MyIntFunction to the template parameter T. Generally, you can specify the first, but omit the second if the compiler can infer the second template parameter. In this case, this is not an option however, because you want to specify the second parameter explicitly.
The second template parameter has a dependency (T) on the first template parameter. Therefore, reversing the order of the template parameters is also not an option.
Your best bet would be to define it in a way similar to what Richard suggested:
template<class T>
void Foo(T f)
{
int a(1);
f(a); // this forces f to be a function taking an int as parameter
}
Here is a dirty implementation which basically does what the OP was asking for. It depends on too many assumptions, but could be at least something to discuss. The idea is to specify in advance all possible types which can serve as function argument, and then deduce this type.
#include<iostream>
template<typename T>
struct TD; //type display
template<typename FunctionType, typename T, typename ... Ts>
struct ArgumentDeduction
{
typedef typename std::conditional<std::is_same<void, typename std::result_of<FunctionType(T)>::type>::value
, T
, typename ArgumentDeduction<FunctionType, Ts ...>::type
>::type type;
};
template<typename FunctionType, typename T>
struct ArgumentDeduction<FunctionType, T>
{
typedef typename std::conditional<std::is_same<void, typename std::result_of<FunctionType(T)>::type>::value
, T
, void
>::type type;
};
template<typename FunctionType
, typename T = typename ArgumentDeduction<FunctionType, int, double>::type >
void foo()
{
TD<T>();
}
struct AvoidConversion
{
struct DummyType{};
template<typename T> DummyType operator()(T x) { return DummyType(); }
};
struct Bar : public AvoidConversion
{
using AvoidConversion::operator();
void operator()(int x);
//void operator()(double x); //try also this
};
int main()
{
foo<Bar>(); //calls the foo<Bar,int> version
}
One main assumption here is the form of the Bar functor, which in principle accepts any type, but has a relevant implementation of type void only for the single allowed type.
Again, I don't think this is rather useful, but I guess this comes closest to the OP's question up to now.
DEMO
EDIT: Otherwise, i.e. without AvoidConversion in the code above, the compiler will perform an implicit conversion and the argument deduction gives true for all types which are convertible into each other (such that, e.g., int is deduced when there is only a function taking double).
If someone sees a way to avoid this ugly AvoidConversion hack and deduce the parameter type somehow more elegant, I would be interested in seeing that.

operator() template specialization

I'm trying to do specialization to template operator, the template looks like this:
template <typename Iterator1, typename Iterator2>
ResultType operator()(Iterator1 a, Iterator2 b, size_t size, ResultType worst_dist = -1) const
after i did the specialization that looks like this:
template <>
float operator()<float*,float*>(float* a, float const* b, unsigned long size, float worst_dist = -1) const
i get an error during compilation :
Cannot specialize a function 'operator()' within class scope
All those function are in struct template
I'll be glad to get some help.
thanks.
Why do you want to specialize this operator anyway? You won't be able to call it using the syntax which depends on specializations (i.e. explicit providing the [some of] the template arguments) anyway! Just use overloading and you should be fine. Although it is sometimes desirable or even necessary to use the notation where you explicitly specify the template arguments, it tends to be not that important for functions in general to use specialization rather than overloading.
I just read things up in the standard and actually is possible to provide an explicit specialization, however it has to be outside of the class definition. For example:
#include <iostream>
struct foo
{
template <typename T> void operator()(T const&) {
std::cout << "general\n";
}
};
template <>
void foo::operator()<int>(int const&) {
std::cout << "int spec\n";
}
int main()
{
foo f;
f(1.2);
f(1);
f<double>(1); // <-- ERROR: doesn't work!
}
This would have worked the same using overloading. Using explicitly specified template arguments still doesn't work, though.

Why can't C++ infer the template type?

Why can't the compiler figure out these template parameters? Is there a way to make it do so?
(I'm using Visual Studio 2010.)
template<typename T, typename TFunc>
void call(TFunc func) { func(T()); }
void myfunc(void *) { }
int main() { call(myfunc); }
T appears nowhere in the parameter list so T cannot be deduced from the function arguments. All types to be deduced must appear in deduced contexts in the parameter list. For example,
template <typename TReturn, typename TParameter>
void call(TReturn (*f)(TParameter))
{
f(TParameter());
}
Template parameter deduction for function templates only works based on function arguments, nothing else. The function definition is never looked at for the purpose of determining the template parameters, so your parameter T cannot possibly be deduced.
You could remedy your situation by incorporating the type into the function signature: Since you expect the outer function to be called with a function itself, make that explicit:
template <typename T> void foo(void(*f)(T))
{
T x;
f(x);
// ...
}
Combine function overloading with functors, and it becomes impossible in the general case to determine what arguments can be passed to a callable entity.
Consider, for example
struct FunctorExample {
void operator()(int x) {...}
std::string operator()(const std::string& ) {...}
};
If there were some way to coax the compiler to pattern match on arguments, it would have to have undefined or error behavior when applied to FunctorExample.
Instead, the trend seems to be that when you want to template metaprogram with functors, you specify the functor and argument list. Examples (off the top of my head) being boost::result_of and boost::fusion.
Edit: That said, if you're willing to restrict your attention somewhat, and you can use some C++11 syntax (decltype), you can arrange to introspect a bit more:
// Support functors with a very simple operator():
template <typename T> struct argument :
public argument<decltype(&T::operator())> {};
// Pointers to member functions
template <typename C, typename R, typename A> struct argument<R(C::*)(A)>
{typedef A type;};
// Function types
template <typename R, typename A> struct argument<R(A)> {typedef A type;};
// Function pointer types.
template <typename R, typename A> struct argument<R(*)(A)> {typedef A type;};
// Now for call:
template <typename FuncType>
void call(FuncType func) {
typedef typename argument<FuncType>::type Arg;
func(Arg());
}
// example:
class FunctorInt {public: int operator()(int ) {return 0;};};
void myfunc(void *) {}
int main() {
call(myfunc);
call(FunctorInt());
}
Variadic templates could be used to expand this stuff to support more than one argument.