Passing function as template argument to a member function - c++

I am trying to pass function as template argument to a function in a class, but there is some mistake. The code is giving an error error: missing template arguments before 'obj'. How can I fix this so that it compiles?
#include<iostream>
double sum_fun(const double &a, const double &b)
{ std::cout<<a+b<<"\n"; }
template <typename F>
class B
{
public:
void fb()(F f1)
{
f1(10.1,10.2);
}
};
int main()
{
B obj(sum_fun); //error
obj.fb(); //error
return 0;
}

There is a misunderstanding of how classes work.
int main()
{
B obj(sum_fun); // calls B constructor with parameter `sum_fun`
obj.fb(); // calls member function B::fb() with no parameters
return 0;
}
Both lines raise an error as
Your class has no constructor which takes a single parameter.
void fb()(F f1) is illegal syntax. To declare a member function, use only one set of parentheses: either void fb() or void fb(F f1). The latter is incorrect in our case, as your member function call obj.fb() passes no parameters.
To fix this, write up a constructor, store the function as a member variable, and use that variable in the function fb().
template <typename F>
class B
{
public:
// constructor, initialises member `m_func` through member initialisation
B(F func) : m_func(func) {}
void fb()
{
m_func(10.1,10.2);
}
private:
F m_func;
};
In C++17, thanks to automatic template deduction, no errors are now emitted. But in lower standards (e.g. C++11), template deduction is lacking and thus, the full templated type needs to be specified when declaring obj.
So in standards below C++17, the main function should be:
int main()
{
// C++11: using a function pointer to denote type
B<double(*)(const double&, const double&)> obj(sum_fun);
// ok in C++17, looks cleaner too
// B obj(sum_fun);
obj.fb();
return 0;
}
Here, double(*)(const double&, const double&) is a function pointer, i.e. a pointer to a function which returns a double and takes two parameters, both of type const double&. Function pointers may be considered as a type, which satisfies the template (template<typename F>).
Just like we do std::vector<int> and std::vector<double>, we can also do std::vector<double(*)(const double&, const double&)> to denote a vector of functions returning double and taking const double& as parameters.
And by the way, sum_fun also raises a warning: nothing is returned even though the return type is double... better specify void as the return type instead.
C++11 Demo
C++17 Demo
Is it possible to pass function as argument directly to B::fb() instead of creating constructor B::B(F) and storing in local variable?
Certainly.
#include <iostream>
void sum_fun(const double& a, const double& b)
{
std::cout << a+b << "\n";
}
template <typename F>
class B
{
public:
void fb(F func)
{
func(10.1,10.2);
}
};
int main()
{
B<void(*)(const double&, const double&)> obj;
obj.fb(sum_fun);
return 0;
}
Note that the member function fb now takes a single parameter func, which we then call. Note also that in C++17, we now can't instantiate the obj with B obj; because this would be ambiguous and the template can't be deduced automatically. Instead, we need to specify the full type B<void(*)(const double&, const double&)>.
However, a recommended alternative over function pointers is to use std::function, which is more versatile and offers a more readable syntax. (std::function Demo)

In C++17 you're allowed to use auto in template paramter list:
template <auto F>
class B
{
public:
void fb()
{
F(10.1,10.2);
}
};
You can then do B<sum_fun>:
int main()
{
B<sum_fun> obj{};
obj.fb();
return 0;
}

Related

Setter of a lambda function?

Consider the following dumb example :
class MyClass
{
public:
template <class Function>
inline double f(double x, Function&& function)
{
return function(x);
}
};
With this class, I can call MyClass::f(x, function), with a lambda function to execute it on x, with (I hope) no overhead. My question is : what would be the equivalent with the function as a settable member of the MyClass ?
class MyClass
{
public:
inline double f(double x)
{
return _function(x);
}
// What are the setter and the type of the protected member _function ?
};
Lambda functions (as well as some other types of "callable" functions) can be wrapped and stored using the std::function template class, found in the <functional> header. Its template parameter is a function signature with the syntax
ReturnType(ArgumentType1, ArgumentType2, ...)
so in your case the whole function wrapper type becomes
std::function<double(double)>
and thus, your code becomes
class MyClass
{
public:
inline double f(double x)
{
return _function(x);
}
void setFunction(std::function<double(double)> && f)
{
_function = f;
}
private:
std::function<double(double)> _function;
};
std::function is "more" than a wrapper for function pointers. As you might know, lambda functions can capture part of the variable context, which needs to be stored somewhere. std::function does this for you transparently.
Note that std::function does not support overloaded signatures / templated call operators for functors. When assigning a functor with a call-operator signature like T operator()(T value) to a std::function<double(double)>, it can only be called with this signature. So there is no std::function<T(T)> (unless T is already known, such as a template parameter of your class).
An alternative which might be more efficient in some cases (you need to benchmark / profile it), is to make your whole class a template class with the function type parameter being the template parameter. Then you can store a function as a member:
template<typename Function>
class MyClass
{
public:
MyClass(Function && f) :
_function(f)
{}
inline double f(double x)
{
return _function(x);
}
private:
Function _function;
};
In order to create such an object, you need to specify the template parameter, like this:
auto myLambda = [](double x){ return x * 0.25; };
MyClass<decltype(myLambda)> myObject { myLambda };
To avoid this ugly syntactic overhead, add a "maker" function which takes advantage of template type deduction:
template<typename Function>
auto makeMyClass(Function && f) -> MyClass<Function> {
return MyClass<Function>(f);
}
Then, the code becomes more readable, with use of auto again:
auto myLambda = [](double x){ return x * 0.25; };
auto myObject = makeMyClass(myLambda);
You would have to use an std::function wrapper, possibly letting the constructor initialize it from an input callable object:
#include <functional> // <== REQUIRED FOR std::function
class MyClass
{
public:
template<typename F>
MyClass(F&& f) : _function(std::forward<F>(f)) { }
inline double f(double x)
{
return _function(x);
}
private:
std::function<double(double)> _function;
};
Notice, that this may bring you some run-time overhead, but the design is simple and flexible. Unless you can prove this run-time overhead is a bottleneck for your software's performance requirements, this run-time overhead should not be a concern.

Can a function type be a class template parameter?

The code below is rejected by VC++ 2012 with "error C2207: 'A::bar' : a member of a class template cannot acquire a function type".
int Hello(int n)
{
return n;
}
template<class FunctionPtr>
struct A
{
A(FunctionPtr foo)
: bar(foo)
{}
FunctionPtr bar;
};
int main()
{
A<decltype(Hello)> a(Hello);
return 0;
}
Why?
gcc is a bit more friendly regarding this error :
error: field 'A<int(int)>::bar' invalidly declared function type
The simplest solution is to declare bar as a function pointer :
FunctionPtr *bar;
In this case, decltype(Hello) evaluates to int(int) not int(*)(int).
Variables cannot have function types. You declare bar to be FunctionPtr which is decltype(Hello) which evaluates to int (int), not a function pointer type.
It's confusing because of some inconsistencies inherited from C. When you define the constructor for A as taking a FunctionPtr you might imagine you'd get the same error. However, function parameters declared as having an array or function type automatically (unfortunately, inconveniently) get turned into pointer types. So even though foo is declared to have a function type it actually has function pointer type and works fine.
But this rule applies only to function parameters and not other variables, so bar actually does have a function type, which is not legal.
Adding on the other answers, you can take advantage of the fact that:
decltype(Hello) evaluates to int (int) (not to a function pointer type);
a function is implicitly convertible to a pointer to itself; this conversion happens pretty much everywhere (e.g. pass function by value (?) instead of function pointer?).
The following code:
#include <type_traits>
template<class F>
struct A
{
A(F foo) : bar(foo) {}
typename std::conditional<std::is_function<F>::value,
typename std::add_pointer<F>::type,
F>::type bar;
};
is a generic solution allowing the same syntax for functions, function pointers, functors and lambdas:
#include <type_traits>
#include <iostream>
void Hello() { std::cout << "Function\n"; }
struct Hello2 { void operator()() { std::cout << "Struct\n"; } };
void Hello3() { std::cout << "Function pointer\n"; }
template<class F>
struct A
{
A(F foo) : bar(foo) { bar(); }
std::conditional_t<std::is_function<F>::value, std::add_pointer_t<F>, F> bar;
};
int main()
{
A<decltype(Hello)> a(Hello);
Hello2 h2;
A<decltype(h2)> b(h2);
A<decltype(&Hello3)> c(&Hello3);
auto Hello4 = []() { std::cout << "Lambda\n"; };
A<decltype(Hello4)> d(Hello4);
}
(here I've slightly changed the solution taking advantage of C++14 features).
Indeed std::function is a (not always better) alternative.

'Incomplete type' error declaring pointer-to-member function template parameter for std::function

Here's the declaration:
#include <functional>
class A { ... };
double fA( std::function<double((A::*)(double))> fp) { ... }
which gives me error
In function ‘double fA(std::function)’:
tb.cpp:32:8: error: ‘fp’ has incomplete type
Though there is no problem with
double fA( double ((A::*fp)(double)) ) { ... }
What's the right way to supply this type as a template parameter to std::function?
I am not really sure of what you really want. The argument to std::function must be a free function signature as stated in the standard:
template<class R, class... ArgTypes>
class function<R(ArgTypes...)>;
Note that the argument is the signature of the operator() that will be offered by the function object. It cannot be a pointer-to-member to a different type, it is just the return type and the arguments to the std::function<> object being created.
The extra set of parenthesis in the function declaration could indicate that you actually want to create a std::function function object that takes as argument a pointer to member and returns a double. If that is the case, the signature of the argument to the std::function is missing the return type:
std::function<double (void (A::*)(double))> fp;
Which could be initialized with:
double myfunc( void (A::*mptr)(double) ) {}
// ...
fp = myfunc;
Ended up doing something very similar to #chris's suggestion, the code from his example is the following:
#include <functional>
#include <iostream>
struct S {
void foo() {std::cout << i;};
int i;
};
void bar(std::function<void()> func) {
func();
}
int main() {
S s1, s2;
s1.i = 5;
s2.i = 6;
bar(std::bind(&S::foo, s1));
bar(std::bind(&S::foo, s2));
}

Nested bind expressions

This is a followup question to my previous question.
#include <functional>
int foo(void) {return 2;}
class bar {
public:
int operator() (void) {return 3;};
int something(int a) {return a;};
};
template <class C> auto func(C&& c) -> decltype(c()) { return c(); }
template <class C> int doit(C&& c) { return c();}
template <class C> void func_wrapper(C&& c) { func( std::bind(doit<C>, std::forward<C>(c)) ); }
int main(int argc, char* argv[])
{
// call with a function pointer
func(foo);
func_wrapper(foo); // error
// call with a member function
bar b;
func(b);
func_wrapper(b);
// call with a bind expression
func(std::bind(&bar::something, b, 42));
func_wrapper(std::bind(&bar::something, b, 42)); // error
// call with a lambda expression
func( [](void)->int {return 42;} );
func_wrapper( [](void)->int {return 42;} );
return 0;
}
I'm getting a compile errors deep in the C++ headers:
functional:1137: error: invalid initialization of reference of type ‘int (&)()’ from expression of type ‘int (*)()’
functional:1137: error: conversion from ‘int’ to non-scalar type ‘std::_Bind<std::_Mem_fn<int (bar::*)(int)>(bar, int)>’ requested
func_wrapper(foo) is supposed to execute func(doit(foo)). In the real code it packages the function for a thread to execute. func would the function executed by the other thread, doit sits in between to check for unhandled exceptions and to clean up. But the additional bind in func_wrapper messes things up...
At the beginning, please let me introduce 2 key points:
a: When using nested std::bind, the inner std::bind is evaluated first, and the return value will be substituted in its place while the outer std::bind is evaluated. That means std::bind(f, std::bind(g, _1))(x) executes as same as f(g(x)) does. The inner std::bind is supposed to be wrapped by std::ref if the outer std::bind wants a functor rather than a return value.
b: The r-value reference cannot be correctly forwarded to the function by using std::bind. And the reason has already been illustrated in detail.
So, let's look at the question. The most importance function here might be func_wrapper which is intended to perform 3 purposes:
Perfect forwarding a functor to doit function template at first,
then using std::bind to make doit as a closure,
and letting func function template execute the functor returned by std::bind at last.
According to point b, purpose 1 cannot be fulfilled. So, let's forget perfect forwarding and doit function template has to accept a l-value reference parameter.
According to point a, purpose 2 will be performed by using std::ref.
As a result, the final version might be:
#include <functional>
int foo(void) {return 2;}
class bar {
public:
int operator() (void) {return 3;};
int something(int a) {return a;};
};
template <class C> auto func(C&& c) -> decltype(c()) { return c(); }
template <class C> int doit(C&/*&*/ c) // r-value reference can't be forwarded via std::bind
{
return c();
}
template <class C> void func_wrapper(C&& c)
{
func(std::bind(doit<C>,
/* std::forward<C>(c) */ // forget pefect forwarding while using std::bind
std::ref(c)) // try to pass the functor itsself instead of its return value
);
}
int main(int argc, char* argv[])
{
// call with a function pointer
func(foo);
func_wrapper(foo); // error disappears
// call with a member function
bar b;
func(b);
func_wrapper(b);
// call with a bind expression
func(std::bind(&bar::something, b, 42));
func_wrapper(std::bind(&bar::something, b, 42)); // error disappears
// call with a lambda expression
func( [](void)->int {return 42;} );
func_wrapper( [](void)->int {return 42;} );
return 0;
}
But, if you really want to achieve purpose 1 and 2, how? Try this:
#include <functional>
#include <iostream>
void foo()
{
}
struct bar {
void operator()() {}
void dosomething() {}
};
static bar b;
template <typename Executor>
void run(Executor&& e)
{
std::cout << "r-value reference forwarded\n";
e();
}
template <typename Executor>
void run(Executor& e)
{
std::cout << "l-value reference forwarded\n";
e();
}
template <typename Executor>
auto func(Executor&& e) -> decltype(e())
{
return e();
}
template <bool b>
struct dispatcher_traits {
enum { value = b };
};
template <typename Executor, bool is_lvalue_reference>
class dispatcher {
private:
static void dispatch(Executor& e, dispatcher_traits<true>)
{
run(e);
}
static void dispatch(Executor& e, dispatcher_traits<false>)
{
run(std::ref(e));
}
public:
static void forward(Executor& e)
{
dispatch(e, dispatcher_traits<is_lvalue_reference>());
}
};
template <typename Executor>
void func_wrapper(Executor&& e)
{
typedef dispatcher<Executor,
std::is_lvalue_reference<Executor>::value>
dispatcher_type;
func(std::bind(&dispatcher_type::forward, std::ref(e)));
}
int main()
{
func_wrapper(foo); // l-value
func_wrapper(b); // l-value
func_wrapper(bar()); // r-value
func_wrapper(std::bind(&bar::dosomething, &b)); // r-value
func_wrapper([](){}); // r-value
}
Let me explain some points:
To reduce lots of return statements, changing functor signature from int() to void().
The 2 run() function templates are used to check whether the original functor parameter is perfect forwarded or not.
dispatcher_traits is going to map bool constant to type.
You'd better name dispatcher::forward to differ from dispatcher::dispatch or you have to invoke std::bind template with dispatcher::forward's signature.
Looking at this the second time now, and I think I have a plausable explanation for the first error you are seeing.
In this case, it's more helpful to look at the complete error and the template instantiations that lead up to it. The error printed by my compiler (GCC 4.4), for example, ends with the following lines:
test.cpp:12: instantiated from ‘decltype (c()) func(C&&) [with C = std::_Bind<int (*(int (*)()))(int (&)())>]’
test.cpp:16: instantiated from ‘void func_wrapper(C&&) [with C = int (&)()]’
test.cpp:22: instantiated from here
/usr/include/c++/4.4/tr1_impl/functional:1137: error: invalid initialization of reference of type ‘int (&)()’ from expression of type ‘int (*)()’
Now looking at this bottom-up, the actual error message seems correct; the types the compiler has deduced are incompatible.
The first template instantiation, at func_wrapper, clearly shows what type the compiler has deduced from the actual parameter foo in func_wrapper(foo). I personally expected this to be a function pointer, but it is in fact a function reference.
The second template instantiation is hardly readable. But messing around with std::bind a bit, I learned that the format of the textual representation GCC prints for a bind functor is roughly:
std::_Bind<RETURN-TYPE (*(BOUND-VALUE-TYPES))(TARGET-PARAMETER-TYPES)>
So tearing it apart:
std::_Bind<int (*(int (*)()))(int (&)())>
// Return type: int
// Bound value types: int (*)()
// Target parameter types: int (&)()
This is where the incompatible types start. Apparently, even though c in func_wrapper is a function reference, it turns into a function pointer once passed to std::bind, resulting in the type incompatibility. For what it's worth, std::forward doesn't matter at all in this case.
My reasoning here is that std::bind only seems to care about values, and not references. In C/C++, there's no such thing as a function value; there's only references and pointers. So when the function reference is dereferenced, the compiler can only meaningfully give you a function pointer.
The only control you have over this is your template parameters. You will have to tell the compiler that you're dealing with a function pointer from the start to make this work. It's probably what you had in mind anyways. To do that, explicitly specify the type you want for the template parameter C:
func_wrapper<int (*)()>(foo);
Or the more brief solution, explicitly take the function's address:
func_wrapper(&foo); // with C = int (*)()
I'll get back to you if I ever figure out the second error. :)

Can you use keyword explicit to prevent automatic conversion of method parameters?

I know you can use C++ keyword 'explicit' for constructors of classes to prevent an automatic conversion of type. Can you use this same command to prevent the conversion of parameters for a class method?
I have two class members, one which takes a bool as a param, the other an unsigned int. When I called the function with an int, the compiler converted the param to a bool and called the wrong method. I know eventually I'll replace the bool, but for now don't want to break the other routines as this new routine is developed.
No, you can't use explicit, but you can use a templated function to catch the incorrect parameter types.
With C++11, you can declare the templated function as deleted. Here is a simple example:
#include <iostream>
struct Thing {
void Foo(int value) {
std::cout << "Foo: value" << std::endl;
}
template <typename T>
void Foo(T value) = delete;
};
This gives the following error message if you try to call Thing::Foo with a size_t parameter:
error: use of deleted function
‘void Thing::Foo(T) [with T = long unsigned int]’
In pre-C++11 code, it can be accomplished using an undefined private function instead.
class ClassThatOnlyTakesBoolsAndUIntsAsArguments
{
public:
// Assume definitions for these exist elsewhere
void Method(bool arg1);
void Method(unsigned int arg1);
// Below just an example showing how to do the same thing with more arguments
void MethodWithMoreParms(bool arg1, SomeType& arg2);
void MethodWithMoreParms(unsigned int arg1, SomeType& arg2);
private:
// You can leave these undefined
template<typename T>
void Method(T arg1);
// Below just an example showing how to do the same thing with more arguments
template<typename T>
void MethodWithMoreParms(T arg1, SomeType& arg2);
};
The disadvantage is that the code and the error message are less clear in this case, so the C++11 option should be selected whenever available.
Repeat this pattern for every method that takes the bool or unsigned int. Do not provide an implementation for the templatized version of the method.
This will force the user to always explicitly call the bool or unsigned int version.
Any attempt to call Method with a type other than bool or unsigned int will fail to compile because the member is private, subject to the standard exceptions to visibility rules, of course (friend, internal calls, etc.). If something that does have access calls the private method, you will get a linker error.
No. explicit prevents automatic conversion between specific classes, irrespective of context. And of course you can't do it for built-in classes.
The following is a very basic wrapper that can be used to create a strong typedef:
template <typename V, class D>
class StrongType
{
public:
inline explicit StrongType(V const &v)
: m_v(v)
{}
inline operator V () const
{
return m_v;
}
private:
V m_v; // use V as "inner" type
};
class Tag1;
typedef StrongType<int, Tag1> Tag1Type;
void b1 (Tag1Type);
void b2 (int i)
{
b1 (Tag1Type (i));
b1 (i); // Error
}
One nice feature of this approach, is that you can also distinguish between different parameters with the same type. For example you could have the following:
class WidthTag;
typedef StrongType<int, WidthTag> Width;
class HeightTag;
typedef StrongType<int, HeightTag> Height;
void foo (Width width, Height height);
It will be clear to the clients of 'foo' which argument is which.
Something that might work for you is to use templates. The following shows the template function foo<>() being specialized for bool, unsigned int, and int. The main() function shows how the calls get resolved. Note that the calls that use a constant int that don't specify a type suffix will resolve to foo<int>(), so you'll get an error calling foo( 1) if you don't specialize on int. If this is the case, callers using a literal integer constant will have to use the "U" suffix to get the call to resolve (this might be the behavior you want).
Otherwise you'll have to specialize on int and use the "U" suffix or cast it to an unsigned int before passing it on to the unsigned int version (or maybe do an assert that the value isn't negative, if that's what you want).
#include <stdio.h>
template <typename T>
void foo( T);
template <>
void foo<bool>( bool x)
{
printf( "foo( bool)\n");
}
template <>
void foo<unsigned int>( unsigned int x)
{
printf( "foo( unsigned int)\n");
}
template <>
void foo<int>( int x)
{
printf( "foo( int)\n");
}
int main ()
{
foo( true);
foo( false);
foo( static_cast<unsigned int>( 0));
foo( 0U);
foo( 1U);
foo( 2U);
foo( 0);
foo( 1);
foo( 2);
}
The currently accepted answer (using a private templated function) is nice, but outdated. With C++11, we can use deleted functions instead:
#include <iostream>
struct Thing {
void Foo(int value) {
std::cout << "Foo: value" << std::endl;
}
template <typename T>
void Foo(T value) = delete;
};
int main() {
Thing t;
int int_value = 1;
size_t size_t_value = 2;
t.Foo(int_value);
// t.Foo(size_t_value); // fails with below error
// error: use of deleted function
// ‘void Thing::Foo(T) [with T = long unsigned int]’
return 0;
}
This conveys the intent of the source code more directly and supplies the user with a clearer error message when trying to use the function with disallowed parameter types.
Compiler gave "ambiguous call" warning, which will be sufficient.
I was doing TDD development and didn't realize I forgot to implement the corresponding call in the mock object.
bool IS an int that is limited to either 0 or 1. That is the whole concept of return 0;, it is logically the same as saying return false;(don't use this in code though).
You could also write an int version that calls the bool one.