I'm really confused at the documentation of isSomeFunction, as well as at the following code:
static assert(!isFunctionPointer!(typeof(Object.toString))); // makes sense
static assert(!isDelegate!(typeof(Object.toString))); // what??
static assert( isSomeFunction!(typeof(Object.toString))); // what??
Could someone please explain the difference between a "function" and a "function pointer" to me?
Short Answer:
is(T == function) Whether T is a function
isFunctionPointer!T Whether T is a function pointer (and not a delegate)
isDelegate!T Whether T is a delegate
isSomeFunction!T Whether T is a function, a function pointer, or a delegate
Long Answer:
A function is, well, a function.
auto func(int val) {...}
It's a chunk of code with a name that you can call using that name. You give it arguments, it does whatever it does, and it returns a result. You can call it, but you can't pass it around. You need a function pointer for that.
A function pointer is a pointer to a function. So just like int is an int and int* is a pointer to an int, and int is not a pointer to int, a function isn't a function pointer. If you want a function pointer, you need a pointer to a function. The syntax is different from how it is with int, but it's the same concept.
A delegate is a function pointer with state. So for instance, in
int foo(int value)
{
int bar()
{
return value + 5;
}
auto barDel = &bar;
return barDel();
}
void main()
{
auto fooFunc = &foo;
}
foo is a function, bar is a nested function which has access to its outer scope, and barDel is a delegate, because it's a function pointer with state (the outer state that bar has access to). If you pass barDel to another function (or return it), you'll get a closure (unless the function it's passed to takes the delegate by scope, in which case that function guarantees that the delegate will not escape its scope), because that state needs to be put on the heap so that it continues to exist even if the function call that its state comes from has completed when it's called. funcFoo, on the other hand, is a function pointer, because foo doesn't have any outer state. If bar were static, then barDel would also be a function pointer rather than a delegate, because bar would no longer have access to the function that it's in (though its body would then have to be changed, since it would no longer have access to value).
Now, as to your example. Object.toString is a member function of Object. So, it's a function. It has no state associated with it. Functions never do. Its current signature is
string toString();
But because it's a member function of Object, its signature is really something like
string toString(Object this);
this is passed to toString as an argument. It's not state associated with toString. So, &Object.toString is not a delegate. It's just a function pointer. And Object.toString isn't a function pointer, so even if &Object.toString were a delegate, static assert(isDelegate!(typeof(Object.toString))) would still fail, because in order to be a delegate, it must be a function pointer, which it's not. It's a function.
Now, unfortunately, typeof(&Object.toString) is considered to be string function() rather than string function(Object), so using it to call toString with an actual Object takes a bit of work. It can be done, but I don't remember how at the moment (and it's a bit ugly IIRC). But it wouldn't be a delegate regardless, because there's no state associated with it.
If you want a function that you can pass an Object to and have it call a member function, then you could do something like
auto obj = getObjectFromSomewhere();
auto func = function(Object obj){return obj.toString();};
auto result = func(obj);
If you want to associate an object with a member function and be able to call that member function on that object without having to pass the object around, then you just wrap it in a delegate:
auto obj = getObjectFromSomewhere();
auto del = delegate(){return obj.toString();};
auto result = del();
This bit of code should sum things up and illustrate things fairly well:
int foo(int value)
{
int bar()
{
return value + 5;
}
static assert( is(typeof(bar) == function));
static assert(!isFunctionPointer!(typeof(bar)));
static assert(!isDelegate!(typeof(bar)));
static assert( isSomeFunction!(typeof(bar)));
auto barDel = &bar;
static assert(!is(typeof(barDel) == function));
static assert(!isFunctionPointer!(typeof(barDel)));
static assert( isDelegate!(typeof(barDel)));
static assert( isSomeFunction!(typeof(barDel)));
static int boz(int i)
{
return i + 2;
}
static assert( is(typeof(boz) == function));
static assert(!isFunctionPointer!(typeof(boz)));
static assert(!isDelegate!(typeof(boz)));
static assert(isSomeFunction!(typeof(boz)));
auto bozFunc = &boz;
static assert(!is(typeof(bozFunc) == function));
static assert( isFunctionPointer!(typeof(bozFunc)));
static assert(!isDelegate!(typeof(bozFunc)));
static assert( isSomeFunction!(typeof(bozFunc)));
return boz(bar());
}
static assert( is(typeof(foo) == function));
static assert(!isFunctionPointer!(typeof(foo)));
static assert(!isDelegate!(typeof(foo)));
static assert( isSomeFunction!(typeof(foo)));
void main()
{
auto fooFunc = &foo;
static assert(!is(typeof(fooFunc) == function));
static assert( isFunctionPointer!(typeof(fooFunc)));
static assert(!isDelegate!(typeof(fooFunc)));
static assert( isSomeFunction!(typeof(fooFunc)));
}
static assert( is(typeof(Object.toString) == function));
static assert(!isFunctionPointer!(typeof(Object.toString)));
static assert(!isDelegate!(typeof(Object.toString)));
static assert( isSomeFunction!(typeof(Object.toString)));
static assert(!is(typeof(&Object.toString) == function));
static assert( isFunctionPointer!(typeof(&Object.toString)));
static assert(!isDelegate!(typeof(&Object.toString)));
static assert( isSomeFunction!(typeof(&Object.toString)));
isSomeFunction is true for all of them, because they're all either functions, function pointers without state, or delegates.
foo, bar, boz, and Object.toString are all functions, so they're true for is(T == function) but not for the others.
fooFunc, bozFunc, and &Object.toString are function pointers without state, so they're true for isFunctionPointer!T but not for the others.
barDel is a delegate, so it's true for isDelegate!T but not for the others.
Hopefully, that clears things up for you.
Related
I have been trying to assign class's member function to a std::function but it throws compile time error Failed to specialize function template 'unknown-type std::invoke(_Callable &&,_Types &&...)
Below is the header file of that class :
class TypeAnalysis {
public:
bool AnalysisHelper(std::string filePath);
void createTypeTable(std::string dir, std::string pattern, size_t nThread = 3);
std::vector<std::string> getFiles(std::string dir, std::vector<std::string> patterns);
private:
};
And below is createtypeTable function where I am assigning AnalysisHelper method to std::fnuction object.
void TypeAnalysis::createTypeTable(std::string dir, std::string pattern, size_t nThread)
{
Threadpool<bool, std::string> tp(10);
DataContext dc;
tp.start();
std::vector<std::string> patterns = SH::split(pattern);
std::vector<std::string> files = getFiles(dir, patterns);
std::function<bool(std::string)> w = &TypeAnalysis::AnalysisHelper; //I think issue is here
try {
if (files.size() > 0) {
for (size_t i = 0; i < files.size(); i++) {
WorkItem<bool, std::string> *wi1 = new WorkItem<bool, std::string>(&w, &files[i]);
tp.doWork(wi1);
}
}
}
catch (std::exception ex) {
std::cout << ex.what();
return;
}
tp.doWork(nullptr);
tp.wait();
DataContext::getContextThreadPool().doWork(nullptr);
}
When I tried to do the same without any class definition (AnalysisHelper was Glabal function and main had same body as createTypeTable), it worked fine.
Any idea whats wrong?
Yes, the problem is in this line:
std::function<bool(std::string)> w = &TypeAnalysis::AnalysisHelper;
I can not see this as correct operation. You are referencing a member function of a class. This member function may need to edit or read one of the member variables of that class. It is not a free function. It is part of the class which should be called for a specific object. So it is normal that C++ denied that.
Edit:
I found this https://isocpp.org/wiki/faq/pointers-to-members#memfnptr-vs-fnptr
How do I pass a pointer-to-member-function to a signal handler, X event callback, system call that starts a thread/task, etc?
Don’t.
Because a member function is meaningless without an object to invoke it on,
you can’t do this directly (if The X Window System was rewritten in
C++, it would probably pass references to objects around, not just
pointers to functions; naturally the objects would embody the required
function and probably a whole lot more)
Issue was I was not binding the method to any object. Changing
std::function<bool(std::string)> w = &TypeAnalysis::AnalysisHelper;
to
std::function<bool(std::string)> w = [=](std::string file) { return this->AnalysisHelper(file); };
worked.
I would like to pass to a function a reference to a class method.
For example:
#include <functional>
struct Foo
{
int f(const int& val) const
{
return val+2;
}
};
int caller(const std::function<int(const int&)>& f)
{
return f(1);
}
int main()
{
caller([](const int& val){return val+2;}); // OK
Foo foo;
caller(foo.f); // WRONG
return 0;
}
How can I fix the second call of caller() (NB: Foo:f() is not static)?
In your case, function f doesn't use any member of Foo so it can be declared static
static int f(const int& val)
and passed as:
caller(&Foo::f);
But suppose that f cannot be declared static and you want to pass "reference" to member function of particular object.
You can use lambda in that case:
Foo foo;
caller(
[&foo](const int& val){
return foo.f(val);
}
);
foo object is captured in square brackets (in this case by reference) so that you can call f member function on that particular object.
Although it is not part of your question, I should add that it is not really useful to pass int by const reference, as you will not gain any performance improvement that way. Actually, your code will run slower than if you pass int by value.
Is it possible to test if a value is a function that can be called? I can test for null easily but after that I have no idea how to ensure the parameter passed in is actually a function?
void myMethod(funcParam)
{
if (funcParam != null)
{
/* How to test if funcParam is actually a function that can be called? */
funcParam();
}
}
void myMethod(funcParam) {
if(funcParam is Function) {
funcParam();
}
}
Of course, the call to funcParams() only works if the parameter list matches - is Function doesn't check for that. If there are parameters involved, one can use typedefs to ensure this.
typedef void MyExpectedFunction(int someInt, String someString);
void myMethod(MyExpectedFunction funcParam, int intParam, String stringParam) {
if(funcParam is MyExpectedFunction) {
funcParam(intParam, stringParam);
}
}
In your case, you want to check if the function can be called with zero arguments.
typedef NullaryFunction();
main () {
var f = null;
print(f is NullaryFunction); // false
f = () {};
print(f is NullaryFunction); // true
f = (x) {};
print(f is NullaryFunction); // false
}
If you just want to know that it is some function, you can test with ... is Function. All callable objects implement Function, but it is technically possible (though often not useful) to implement Function manually without actually being callable. It does make a kind of sense for objects that mock callability through noSuchMethod.
var f = () {};
print(f is Function); // 'true'
var x = (x){};
print(x is Function); // 'true'
In C++ code:
class CWindowUI {
public CWindowUI(const char* title,int width,int height);
.....
};
static int CreateWindow(lua_State *l)
{
int width,height;
char *title;
CWindowUI **winp, *win;
name = (char *) luaL_checkstring(l, 1);
width= lua_tounsigned(l, 2);
height= lua_tounsigned(l, 3);
win = new CWindowUI(title,width,height);
if (win == NULL) {
lua_pushboolean(l, 0);
return 1;
}
winp = (CWindowUI **) lua_newuserdata(l, sizeof(CWindowUI *));
luaL_getmetatable(l, "WindowUI");
lua_setmetatable(l, -2);
*winp = win;
return 1;
}
In Lua code:
local win = CreateWindow("title", 480, 320);
win:resize(800, 600);
Now my question is:
Function CreateWindow will return a object named win and the function resize is not defined. How do I get a notification when I call an undefined function in Lua?
The notification shall include the string "resize" and the arguments 800,600.
I want to modify the source to map the undefined function onto the callback function but it is incorrect .
How do I get a notification when I call an undefined function in lua.
You don't. Not in the way that you mean it.
You can hook an __index metamethod onto your registered "WindowUI" metatable (*groan*). Your metamethod will only get the userdata it was called on and the key that was used.
But you cannot differentiate between a function call and simply accessing a member variable, since Lua doesn't differentiate between these. If you return a function from your metamethod, and the user invokes the function-call operator on the return from the metamethod, then it will be called. Otherwise, they get a function to play with as they see fit. They can store it, pass it around, call it later, whatever. It's a value, like any other.
I noticed that i can set a return type on a function to 'Void' aswell as 'void' and just wondered if there was and benefit of either?
Void (with uppercase "v") was ActionScript 2 version of ActionScript 3 void.
AS3 docs (void):
Specifies that a function cannot return any value. The void type is a special type that contains exactly one value: undefined. It is special in that its use is limited to the return type of a function. You cannot use void as a type annotation for a property.
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/specialTypes.html#void
AS2 docs (Void):
The Void data type has one value, void, and is used in a function definition to indicate that the function does not return a value, as shown in the following example:
//Creates a function with a return type Void
function displayFromURL(url:String):Void {}
http://help.adobe.com/en_US/AS2LCR/Flash_10.0/help.html?content=00000037.html
No there isn't. void type just says the compiler that no value will be returned.
void type indicates to the compiler that the function you have written will not return any value, in the other side if you indicate other type int than void the compiler expect that you return int.
Ex:
function foo(a:int):int
{
// here the compiler expect that somewhere
// in your function you return an int
return a;
}
AS2 = :Void
AS3 = :void