Functions and function pointers in C++ - c++

With reference to the following code
#include <iostream>
using std::cout;
using std::endl;
#include <vector>
using std::vector;
void function() {
cout << "Hello World" << endl;
}
int main() {
vector<void (*) ()> functions;
functions.push_back(function); // (1) no error
functions.push_back(&function); // (2) no error
for (const auto& func : functions) {
func();
}
// vector<decltype(function)> vec; // (3) error
return 0;
}
There seems to be an error when I uncomment (3), I am just trying to understand the reasoning behind this. When I pass in a function as the argument to a templated function does it resolve the type to a function pointer? It would make sense for the compiler to deduce all function types as such to a function pointer but why then does the decltype() not resolve to a function pointer?

decltype(function) is void() - a function.
what you need is the decayed version of a function - void(*)():
std::decay<decltype(function)>::type
std::vector < std::decay<decltype(function)>::type > myPtrFunctionVec;
PS.
if you're working with VC++ (visual stdio) you can easily see the type deduced from decltype by printing typeid(decltype(XXX)).name(). VC++, unlike other compilers, gives the undecorated name of a type. very handy for metaprogramming debugging.
EDIT:
as #Daniel Jour has commented, the solution decltype(&function) workd as well, because the construct &f gives the pointer to f, which is what you need

Related

Pointer to member type incompatible with object type → What is the cause?

Recently I ran into a compiler (GNU g++ 4.9.2) error like this:
ProceduralTimerTaskAdapter.cpp:25:13: error: pointer to member type ‘void (Poco::Util::Timer::)(Poco::Util::TimerTask&)’ incompatible with object type ‘Poco::Util::ProceduralTimerTaskAdapter’
Here is the relevant code (which is almost self-contained, save for the necessary Poco libs):
ProceduralTimerTaskAdapter.h:
#include <Poco/Util/Timer.h>
#include <Poco/Util/TimerTask.h>
#include <Poco/Util/TimerTaskAdapter.h>
#ifndef PROCEDURALTIMERTASKADAPTER_H
#define PROCEDURALTIMERTASKADAPTER_H
using namespace std;
using namespace Poco::Util;
typedef void (*Callback) (TimerTask&);
namespace Poco {
namespace Util {
class ProceduralTimerTaskAdapter : public TimerTaskAdapter <Timer> {
public:
ProceduralTimerTaskAdapter (Callback procedure); // Constructor
void run (); // Method defining the main thread
protected:
~ProceduralTimerTaskAdapter (); // Destructor (not for general use)
private:
ProceduralTimerTaskAdapter (); // Default constructor (not for general use)
Callback procedure; // The callback procedure called by the timer.
};
}
}
#endif
ProceduralTimerTaskAdapter.cpp:
// This is the implementation of the ProceduralTimerTaskAdapter class.
#include <iostream>
#include <Poco/Util/Timer.h>
#include <Poco/Util/TimerTask.h>
#include <Poco/Util/TimerTaskAdapter.h>
#include "ProceduralTimerTaskAdapter.h"
using namespace std;
using namespace Poco::Util;
ProceduralTimerTaskAdapter::ProceduralTimerTaskAdapter (Callback procedure) : TimerTaskAdapter<Timer>::TimerTaskAdapter (*(new Timer ()), procedure)
{
this -> procedure = procedure;
}
ProceduralTimerTaskAdapter::~ProceduralTimerTaskAdapter ()
{
}
void ProceduralTimerTaskAdapter::run ()
{
TimerTask &task = *this;
(this ->* procedure) (task);
}
What I wanna do is, in fact, build an extension of the well-known TimerTaskAdapter to handle callback functions, which are not tied to a specific class (because they are situated in main.cpp, for instance). I override the virtual method run () with a very simple self-made one, which calls the callback. After having handled several different errors, I ended up with this apparent class mismatch I can't solve myself. I even don't understand why the compiler states a class name, whose name is Poco::Util::Timer:: (Why does it end with ::?). As ProceduralTimerTaskAdapter defines a member named procedure, why does the compiler expect another class?
Thank you.
Derive from Poco::Util::TimerTask (like in Poco::Util::TimerTaskAdapter class) and override run method in which you will call procedures.
class ProcedureAdapter : public Poco::Util::TimerTask {
public:
typedef void (*Callback)(TimerTask&);
ProcedureAdapter (Callback c) : callback(c) {;}
void run () {
callback(*this); // call some procedure which takes TimerTask
}
Callback callback;
};
void fun (Poco::Util::TimerTask&) {
cout << "fun was invoked" << endl;
}
void fun2 (Poco::Util::TimerTask&) {
cout << "fun2 was invoked" << endl;
}
int main()
{
Poco::Util::Timer t;
t.schedule (new ProcedureAdapter{&fun},1,1);
t.schedule (new ProcedureAdapter{&fun2},1,1);
The syntax ->* expects a left-hand operator of type pointer to class object (such as this) and a right-hand operator of type pointer to member function of that class. But in
TimerTask &task = *this; // line 24
(this ->* procedure) (task); // line 25
procedure is not a pointer to a member function of ProceduralTimerTaskAdapter. So your code is ill-formed. procedure is simply a pointer to a free (non-member) function taking a TimerTask& and returning void. If ProceduralTimerTaskAdapter is derived from
TimerTask then the following code should compile
TimerTask &task = *this;
(this -> procedure) (task);
or shorter
procedure(*this);
using the fact that pointers to functions can syntactically be used like the function.
Edit. It appears (from your comments to another answer) that your code was ill-formed in yet another way, namely that ProceduralTimerTaskAdapter was not derived from TimerTask. Then, of course already line 24 (not just 25) should produce an error. It seems, therefore, that you didn't show us the precise same code as the one that created the error message, or not all the errors it causes.

Not ambiguous identifier

Visual C++ 2017 compiles the following cleanly, calling the user-defined log:
// Source encoding: UTF-8 with BOM ∩
#include <algorithm> // std::for_each
#include <iostream>
#include <math.h> // ::(sin, cos, atan, ..., log)
#include <string> // std::string
void log( std::string const& message )
{
std::clog << "-- log entry: " << message << std::endl;
}
auto main()
-> int
{
auto const messages = { "Blah blah...", "Duh!", "Oki doki" };
std::for_each( messages.begin(), messages.end(), log ); // C++03 style.
}
I think that's a compiler bug, since I designed the code to show how an identifier can be ambiguous due to name collision with the standard library.
Is it a compiler bug?
Supplemental info: MinGW g++ 7.2 issues several error messages. They're not exactly informative, 15 lines complaining about std::for_each, but evidently they're due to the name collision. Changing the name of log the code compiles nicely.
Update: Further checking indicates that it's clearly a compiler bug, because Visual C++ compiles the following (except when symbol D is defined):
#include <cmath> // std::(sin, cos, atan, ..., log)
#include <string> // std::string
namespace my{ void log( std::string const& ) {} }
using std::log;
using my::log;
auto main()
-> int
#ifdef D
{ return !!log; }
#else
{ auto f = log; return f==my::log; }
#endif
Reported to Microsoft (the new MS bug reporting scheme is very buggy: it thought it was a good idea to word-wrap the code, then refused to let me upload source code file unless I gave it a ".txt" filename extension).
This is a compiler bug because the compiler should not be able to perform template argument deduction for the for_each call.
The only declaration of for_each that could match is defined as [alg.foreach]:
template<class InputIterator, class Function>
Function for_each(InputIterator first, InputIterator last, Function f);
Template argument deduction applied on function parameter f needs the type of the function call argument log to proceed. But log is overloaded, and an overload set of functions does not have a type.
For example, this simpler code should not compile for the same reason:
#include <algorithm> // std::for_each
#include <string> // std::string
void log( std::string const& message );
void log();
auto main()
-> int
{
auto const messages = { "Blah blah...", "Duh!", "Oki doki" };
std::for_each( messages.begin(), messages.end(), log ); //template argument deduction for template parameter Function failed.
}
It works in this version of MSVC because templates (used to be/) are implemented as a kind of macro, so log is passed as a name, and overload resolution is performed at the point where log is called in the body of for_each.
About the edit:
The expression !!log is equivalent to a call to bool operator(bool) there are no template argument deduction, the compiler just can not know which overload of log it can use to make the conversion to bool.
Inside declaration of the form auto x=y, the actual type of x is deduced using template argument deduction [dcl.type.auto.deduct]/4:
If the placeholder is the auto type-specifier, the deduced type T' replacing T is determined using the rules for template argument deduction. [...]
So the behavior of MSVC is wrong but consistent.
Defining your own ::log causes undefined behaviour (no diagnostic required).
From C++17 (N4659) [extern.names]/3:
Each name from the C standard library declared with external linkage is reserved to the implementation for use as a name with extern "C" linkage, both in namespace std and in the global namespace.
Link to related answer.

default function object value as function parameter to be called with a lambda

I want to have a method with a function object with default value as parameter, to be called with a lambda function, like for example:
#include <iostream>
#include <functional>
void func(const std::function<void()>& f = {}){
if(f) f();
else std::cout << "or not" << std::endl;
}
int main() {
func([](){ std::cout << "hello" << std::endl; });
func();
}
but on Visual Studio 2012 this does not compile (it compiles using Visual Studio 2015 or g++, for example), complaining about the default value {}. Change this to:
void func(const std::function<void()>& f = nullptr){
fix the problem.
1) Is that a feature not supported by the compiler?
2) Is there any difference between both?
1) Is that a feature not supported by the compiler?
Your test appears to show that is the case. It is a standard feature, so not supporting it means that the compiler doesn't conform to the standard.
2) Is there any difference between both?
There is no difference. Both the default constructor and the constructor that takes nullptr_t behave exactly the same.

"Incomplete type not allowed " when creating std::ofstream objects

Visual Studio Throws this Strange Error:
Incomplete type not allowed
When I try to create an std::ofstream object. Here is the code I wrote inside a function.
void OutPutLog()
{
std::ofstream outFile("Log.txt");
}
whenever it encounters this Visual Studio throws that Error. Why This Happens?
As #Mgetz says, you probably forgot to #include <fstream>.
The reason you didn't get a not declared error and instead this incomplete type not allowed error has to do with what happens when there is a type that has been "forward declared", but not yet fully defined.
Look at this example:
#include <iostream>
struct Foo; // "forward declaration" for a struct type
void OutputFoo(Foo & foo); // another "forward declaration", for a function
void OutputFooPointer(Foo * fooPointer) {
// fooPointer->bar is unknown at this point...
// we can still pass it by reference (not by value)
OutputFoo(*fooPointer);
}
struct Foo { // actual definition of Foo
int bar;
Foo () : bar (10) {}
};
void OutputFoo(Foo & foo) {
// we can mention foo.bar here because it's after the actual definition
std::cout << foo.bar;
}
int main() {
Foo foo; // we can also instantiate after the definition (of course)
OutputFooPointer(&foo);
}
Notice we could not actually instantiate a Foo object or refer its contents until after the real definition. When we only have the forward declaration available, we may only talk about it by pointer or reference.
What is likely happening is you included some iostream header that had forward-declared std::ofstream in a similar way. But the actual definition of std::ofstream is in the <fstream> header.
(Note: In the future be sure to provide a Minimal, Complete, Verifiable Example instead of just one function out of your code. You should supply a complete program that demonstrates the problem. This would have been better, for instance:
#include <iostream>
int main() {
std::ofstream outFile("Log.txt");
}
...also, "Output" is generally seen as one complete word, not two as "OutPut")

Calling a member function with member data by using for_each

Dear all, I would like to call a member function (that expects a reference) for each object of (let's say) a vector that is a member of the same class, as the following code shows:
#include <functional>
#include <algorithm>
#include <vector>
#include <iostream>
using namespace std;
struct Stuff {
double x;
};
class Test {
public:
void f1(Stuff & thing);
void f2(void);
vector<Stuff> things;
};
void Test::f1(Stuff & thing) {
; // do nothing
}
void Test::f2(void) {
for_each(things.begin(), things.end(), f1);
}
int main(void)
{
return 0;
}
This codes gives me a compiler error related to unresolved overloaded function type . I have tried also with bind, but it seems that the references requisite in f1 is one problem. I know I am missing something important here, so I take this opportunity to solve my problem and to learn. At the moment, I can't install boost, but I would like to know also if boost is useful to solve this problem. Thanks in advance.
The function you want to call cannot be simply identified by f1 but should be referred to as &Test::f1 (as in : member function f1 of class Test)
Function f1 does not take a single argument : as any non-static member function it has an implicit this parameter of type Test * const
Finally, a standard bind won't be able to do the trick because it doesn't handle parameters passed by reference.
Boost.Bind would indeed be a great option :
std::for_each(things.begin(), things.end(), boost::bind(&Test::f1, this, _1));