Why does the following code work?
class foo {
public:
template <typename F>
int Map(F function) const {
return function(2);
}
};
int Double(int n) {
return 2*n;
}
int main(){
foo f;
int n = f.Map(Double);
}
My understanding is that the function accepting the function pointer must have format such as:
void foo(int (*ptf)(int))
So the Map function should look like
int Map(int (*ptf)(int)){
return (*ptf)(2);
}
does the it somehow resolve the function at run-time or at compile-time through template?
the above code was compiled and ran in vc++ 2010
Template are a compile-time concept, so of course it will be resolved during compile time (if what you mean is the template parameter substitution). Try passing something which you can't call like function(2), e.g., some int. This will yield a compile-time error. After substitution, your function will look like
int Map(int (*function)(int)){
return function(2);
}
You don't explicitly need to dereference a function pointer, because both function(2) and (*function)(2) are immediatly converted to a so-called function designator. That itself is dereferenceable again and you can build an endless chain: (***********function)(2) will still work and is still the same as function(2) and (*function)(2).
Related
I have a fairly big project that, regarding this question,
I can summarize with
this structure:
void do_something()
{
//...
}
template<typename F> void use_funct(F funct)
{
// ...
funct();
}
int main()
{
// ...
use_funct(do_something);
}
All is working ok until someone (me) decides to reformat a little
minimizing some functions, rewriting
as this minimum reproducible example:
void do_something(const int a, const int b)
{
//...
}
void do_something()
{
//...
do_something(1,2);
}
template<typename F> void use_funct(F funct)
{
// ...
funct();
}
int main()
{
// ...
use_funct(do_something);
}
And now the code doesn't compile with
error: no matching function for call
where use_funct is instantiated.
Since the error message was not so clear to me
and the changes were a lot I wasted a considerable
amount of time to understand that the compiler
couldn't deduce the template parameter
because do_something could now refer to
any of the overloaded functions.
I removed the ambiguity changing the function name,
but I wonder if there's the possibility to avoid
this error in the future not relying on template
argument deduction.
How could I specify in this case the template argument for do_something(), possibly without referring to a function pointer?
I haven't the slightest idea to express explicitly:
use_funct<-the-one-with-no-arguments->(do_something);
You can wrap the function in a lambda, or pass a function pointer after casting it to the type of the overload you want to call or explicitly specify the template parameter:
use_funct([](){ do_something (); });
use_funct(static_cast<void(*)()>(do_something));
use_funct<void()>(do_something);
Wrapping it in a lambda has the advantage, that it is possible to defer overload resolution to use_func. For example:
void do_something(int) {}
void do_something(double) {}
template<typename F> void use_funct(F funct) {
funct(1); // calls do_something(int)
funct(1.0); // calls do_something(double)
}
int main() {
use_funct([](auto x){ do_something (x); });
}
[...] possibly without referring to a function pointer?
I am not sure what you mean or why you want to avoid that. void() is the type of the function, not a function pointer. If you care about spelling out the type, you can use an alias:
using func_type = void();
use_funct<func_type>(do_something);
So I have a class that takes two template parameters, one is the type, one is the type of the function used, it has a reduce function to apply this function repeatedly to the array. However, I'm getting a compilation error.
function_template_test.cpp: In instantiation of 'class _C<int, int(int, int)>':
function_template_test.cpp:36:33: required from here
function_template_test.cpp:11:17: error: field '_C<int, int(int, int)>::op' invalidly declared function type
BinaryOperator op;
Here is my code. I have a class and the driver code down below in the main method.
#include<iostream>
template<typename _T>
_T addition(_T x,_T y)
{
return x+y;
}
template<typename _T,typename BinaryOperator>
class _C
{
private:
BinaryOperator op;
public:
_C(BinaryOperator op)
{
this->op=op;
}
_T reduce(_T*begin,_T*end)
{
_T _t_=*begin;
++begin;
while(begin!=end)
{
_t_=this->op(_t_,*begin);
++begin;
}
return _t_;
}
_T operator()(_T*begin,_T*end)
{
return this->reduce(begin,end);
}
};
int main(int argl,char**argv)
{
int arr[]={1,4,5,2,9,3,6,8,7};
_C<int,decltype(addition<int>)>_c_=_C<int,decltype(addition<int>)>(addition<int>);
std::cout<<_c_(arr,arr+9)<<std::endl;
return 0;
}
You're specifying function type as the template argument for BinaryOperator, which can't be used as the data member op's type; you can specifty function pointer type instead. e.g.
_C<int,decltype(addition<int>)*>_c_=_C<int,decltype(addition<int>)*>(addition<int>);
// ^ ^
BTW: Names like _C beginning with an underscore are reserved in C++.
Normally when assigning a function to a function pointer you don't explicitly need to add the address of operator (&) as it is not valid to assign the function itself to a variable so the language automatically adds it for you. However when doing decltype on a function name you do get the function type not a function pointer. For example try compiling the following, all the static_asserts should pass:
#include <type_traits>
void foo() {}
int main()
{
auto a = foo;
auto b = &foo;
static_assert(std::is_same_v<decltype(a), decltype(b)>,"a and b are function pointers");
static_assert(!std::is_same_v<decltype(a), decltype(foo)>,"foo is not a function pointer");
static_assert(std::is_same_v<decltype(a), decltype(&foo)>,"&foo is a function pointer");
}
Your code is essentially equivalent to:
#include <type_traits>
void foo() {}
int main()
{
decltype(foo) c = foo;
}
Which doesn't compile. Changing it to this fixes the problem:
#include <type_traits>
void foo() {}
int main()
{
decltype(&foo) c = foo;
}
The fix to your code is to change it to:
_C<int,decltype(&addition<int>)>_c_=_C<int,decltype(&addition<int>)>(addition<int>);
Or you can avoid repeating the types by just constructing directly:
_C<int,decltype(&addition<int>)>_c_(addition<int>);
Or using auto:
auto _c_=_C<int,decltype(&addition<int>)>(addition<int>);
I am making a method pointer wrapper like this:
template<typename OBJECT, typename... ARGS>
method_wrapper<ARGS...> _getWrapper(OBJECT* object, void (OBJECT::*method)(ARGS...))
{
//irrelevant
}
The problem is right at the calling of _getWrapper:
class TestClass
{
void TestMethod(int a, float b, bool c)
{
std::cout<<a<<std::endl;
std::cout<<b<<std::endl;
std::cout<<c<<std::endl;
}
};
int main()
{
TestClass testObj;
method_wrapper<int, float, bool> wrap = _getWrapper<int, float, bool>(&testObj, TestClass::TestMethod);
wrap.callInternal(1000, 3.14, true);
//...
system("pause");
return 0;
}
Not matter in what way I try to pass the arguments in _getWrapper, it still tells me:
no instance of overloaded function matches the argument list
Doesn't OBJECT::*method match TestClass::TestMethod directly? I also tried &TestClass::TestMethod, doesn't match either.
You're specifying the template arguments explicitly when invoking _getWrapper, and the first one is specifed as int for template parameter OBJECT, which is wrong. Because member pointers can't refer into non-class type.
Change
_getWrapper<int, float, bool>(&testObj, TestClass::TestMethod)
to
_getWrapper<TestClass, int, float, bool>(&testObj, &TestClass::TestMethod)
// ~~~~~~~~~~
Note you can just rely on template type deduction, e.g.
_getWrapper(&testObj, &TestClass::TestMethod)
BTW: For taking address from members you should always use & for it.
BTW: I suppose TestClass::TestMethod is public.
While reading some code, I came across this function. I have lots of trouble understanding the signature of the function. What are the things that I need to know before I can make head or tail of the following code?
I have been using C++ for a while now. I know what templates, function pointers are. However, I cannot make out what T::* might mean, what the line starting with _Defer means semantically.
Also, the first line of the function seems quite intimidating. Is there some resource that I can read up before trying to re-assess this code?
template <typename T>
_Defer<void(*(PID<T>, void (T::*)(void)))
(const PID<T>&, void (T::*)(void))>
defer(const PID<T>& pid, void (T::*method)(void))
{
void (*dispatch)(const PID<T>&, void (T::*)(void)) =
&process::template dispatch<T>;
return std::tr1::bind(dispatch, pid, method);
}
Source: https://github.com/3rdparty/libprocess/blob/master/include/process/defer.hpp
This might help clear things up a little:
template<typename T>
using VoidPMemberFn = void(T::*)(); // Pointer to member function of T
// that accepts no arguments and
// returns nothing.
template<typename T>
using DeferResultType = void (*)(const PID<T> &, VoidPMemberFn<T>);
template<typename T>
using DeferSignatureType = DeferResultType<T>(PID<T>, VoidPMemberFn<T>);
template<typename T>
_Defer<DeferSignatureType<T>> defer(const PID<T> &pid, VoidPMemberFn<T> method)
{
// Stuff...
}
EDIT
This might help clarify what the spaghetti in the _Defer template means, and how it relates to the above:
void(* (PID<T>, void (T::*)(void)) )(const PID<T>&, void (T::*)(void))
^-+^-^ ^-------------------------^ ^-------------+------------------^
| argument list |
| |
+-----------------------------------------------+
return type: void(*)(const PID<T> &, void(T::*)(void))
This creates a "signature", like those used with std::function (e.g. std::function<int(float)>).
More examples:
using sig = int(float);
sig gn; // Same as: "int gn(float)", a function declaration
int fn(float x)
{return (int)x;}
int main(int argc, char **argv)
{
// pointer to a function with signature "sig"
sig *pfn = &fn;
return 0;
}
int gn(float x)
{return (int)(x*x);}
This is non-standard non-portable code and hence hard to decode for humans. The return type
_Defer<void(*(PID<T>, void (T::*)(void)))(const PID<T>&, void (T::*)(void))>
is a specialisation of some class template _Defer defined in some header included. It is explained in defube's answer.
However, _Defer<> is not part of the std library specification and hence using it in this way makes the code non-portable and hence non-standard compliant. The same holds for the usage of std::tr1::bind instead of std::bind.
I guess your function's C++14 equivalent is simply
template <typename T>
auto defer(const PID<T>& pid, void (T::*method)())
{
auto dispatch = &process::template dispatch<T>;
return std::bind(dispatch, pid, method);
}
where process must be some class (or base class if defer is a member function) with static template member method dispatch. Thus, defer() returns some function object (see the documentation for std::bind) to be called later.
Note that the return type of std::bind is unspecified by the standard and hence auto (or packaging it into a std::function) the only portable way to handle it.
What I'm trying to do is as follows:
(some data type say x) function_name((same data type x mentioned earlier) variable_name)
{
/* Function body */
}
int main()
{
(data type x mentioned above) var;
function_name(var);
.....
}
for example I've
int function_name(int x)
int main()
{
int y;
function_name(y);
....}
In main(), I pass an int variable through above function
Now I want another function of exactly same body as above function, but just differ in data type of arguments and return type, say
unsigned long long FUNCTION_NAME_SAME_DEFINITION_AS_function_name(unsigned long long x)
Is there a way I can merge the above two functions, without using function overloading? Mean the function detects what data type of variable is passed through it? if I pass argument of type 1 it returns value of data type 1 and if I pass argument of type 2 it returns value of data type 2 .
You mean like a template?
template <typename T>
T function_name(T variable_name)
{
/* Function body */
}
read a book or something.
You can do this with templates.
template <typename T>
T function_name(T var) {
// code
}
int main() {
int foo;
char bar;
function_name(foo); // returns int
function_name(bar); // returns char
}
The compiler will attempt various type combinations with the available template definitions to output a valid function. If it is successful, it will generate a complete function definition with that type.
In reply to: UserCPP: Is it possible? template T function_name{....}, Mean function accepts no data type and in main function I write "variable = function_name()"
This is not possible directly. Function templates can only deduce types from arguments, NOT from return values. You have some options. You could modify by reference rather than returning a value:
template <typename T>
void function_name(T& var) {
// code
}
int main() {
int foo;
char bar;
function_name(foo); // modifies foo as an int
function_name(bar); // modifies bar as a char
}
You could also explicitly state the type:
template <typename T>
T function_name() {
// code
}
int main() {
int foo;
char bar;
foo = function_name<int>(); // returns int
bar = function_name<char>(); // returns char
}
Recommended reading:
Function templates (Specifically, Argument Deduction in Function Templates)