I've full discussed the requirement and my investigations thusfar on my blog: "Can a function expression circumvent closure?"
In summary, when one has this code:
o = new C();
function dumpVariables(){
writeDump(var=variables);
}
o.dumpVariables = dumpVariables;
o.dumpVariables();
Then the writeDump() will reference the CFC's internal variables scope. However if one uses a function expression instead of a declaration:
dumpVariables = function (){
writeDump(var=variables);
};
(The rest of the code being the same, just how the dumpVariables() function is created)
... then - because function expressions use closure when binding variable references, that reference to variables in the writeDump() statement still references the calling code's variables scope, even when it's being called from within the object the function has been injected into.
This is a very simplified repro case for the purposes of asking this question, so the stipulation is that the the function being injected into the object must be created via a function expression, and the other stipulation is that the function expression is the only code I can change. I say this because I'm fully aware of work-arounds for this which don't use function expressions, or leverage changes to the CFC code etc... that's not my problem. The problem I am having and am hoping someone can help with is how one can access the variable context of when the function is called rather than when it's being declared.
Thanks for any insight. I suspect the answer is "cannot be done".
Related
I have couple questions regarding some C++ rules.
Why am I able to call a function/method from outside the class in the namespace when I include the return type? (look at the namespace test2::testclass2 in the code below) i.e. this works:
bool b = testclass1::foo<int>(2);
whereas this doesn't: - (it doesn't even compile - compiler throws that this is function redeclaration)
testclass1::foo<int>(2);
C++ complains that it is a function redeclaration. Is that so?
This line:
bool b = testclass1::foo<int>(2);
gets called first before anything else. Is this because static methods get created always first before anything else in C++?
Where can I find those rules? I have a few C++ books at home, so if someone would be kind enough to either point out a book (and chapter or page) or direct me to a website I would greatly appreciate it.
Here below is the sample (partial) code that I tested at home with Visual Studio 2008:
class testclass1
{
public:
testclass1(void);
~testclass1(void);
template<class A> static bool foo(int i)
{
std::cout <<"in static foo";
return true;
}
};
namespace test2
{
class testclass2
{
public:
testclass2(void);
~testclass2(void);
};
bool b = testclass1::foo<int>(2);
}
EDIT:
A few people mentioned that I need to call this inside the function and this will work without any problem.
I understand that; the only reason I asked this question is because I saw this code somewhere (in someone's elses project) and was wondering how and why this works. Since I never really seen anyone doing it before.
Also, this is used (in multiple places) as a way to call and instantiate a large number of classes like this via those function calls (that are outside). They get called first before anything else is instantiated.
C++ is not Python. You write statements in functions and execution starts from the main method. The reason bool b = ... happens to work is that it's defining the global variable b and the function call is merely the initialization expression.
Definitions can exist outside functions while other statements can only exist inside a function body.
Why am I able to call a function/method from outside the class in the namespace when I include the return type? (look at the namespace test2::testclass2)
Your declaration of b is not inside a function, so you are declaring a global variable. If you were inside a function's scope, your second statement would work, but outside a function it makes no sense.
This also answers your second question.
Of course, you wouldn't be allowed to call it this way (i.e. not as a method of an object) if it weren't a static member function.
You can find the rules on e.g. Koenig lookup and template in the standard documentation -- good luck with navigating that! You're not mentioning which compiler you are testing, but I'm not entirely sure it's compliant!
As Mehrdad points out, you're declaring and initializing a global variable within the test2 namespace: this has nothing to do with static methods.
if you write this inside a function like below then it works without a problem. As mentioned above, you need to call these functions from within a function unless you are using the function to initialize a global variable ...
int main()
{
testclass1::foo<int>(2);
return 0;
}
1. First, a helpful correction: you said "...when I include the return type". I think you might be misunderstanding what the <int> part of testclass1::foo<int>(2) does. It doesn't (necessarily) specify the return type, it just provides a value for the template argument "A".
You could have chosen to use A as the return type, but you have the return type hard-coded to "bool".
Basically, for the function as you have written it you will always need to have the <> on it in order to call it. C++ does allow you to omit the <args> off the function when the type can be deduced from the function arguments; in order to get it to do that you have to use the type argument A in your function arguments. For instance if you declared the function this way instead then you could call it without the <>:
template<class A> static bool foo(A i);
In which case it you could call "foo(2)" and it would deduce A to be "int" from the number two.
On the other hand there isn't any way to make it deduce anything based on what you assign the function to. For template argument deduction it only looks at the arguments to the function, not what is done with the result of calling the function. So in:
bool b = testclass1::foo(2);
There is no way to get it to deduce "bool" from that, not even if you made A the return type.
So why doesn't the compiler just tell you "you needed to use <> on the function"? Even though you declared foo once as a template function, you could have also overloaded it with a non-template version too. So the compiler doesn't just automatically assume that you're trying to call a template function when you leave the <> off the call. Unfortunately having NOT assumed you were calling template-foo and not seeing any other declaration for foo, the compiler then falls back on an old C style rule where for a function that takes an int and returns an int, in a very old dialect of C you didn't need to declare that kind of before using it. So the compiler assumed THAT was what you wanted - but then it notices that template-foo and old-crufty-C-foo both take an int parameter, and realizes it wouldn't be able to tell the difference between them. So then it says you can't declare foo. This is why C++ compilers are notorious for giving bad error messages - by the time the error is reported the compiler may have gone completely off the rails and be talking about something that is three or four levels removed from your actual code!
2. Yes you're exactly right.
3. I find that the C++ references and whitepapers that IBM makes available online are the most informative. Here's a link to the section about templates: C++ Templates
Recently, I had a bug where, we changed the function from
void update_waypoint_heading(const double new_observation, waypoint)
{
// ....
waypoint.heading = default_heading_deg * waypoint.some_magic_number
}
// Call the function and the function will calculate new heading and mutate heading in waypoint
update_waypoint_heading(new_observation, waypoint);
to
double update_waypoint_heading(const double new_observation, waypoint)
{
// ....
return default_heading_deg * waypoint.some_magic_number
}
// Here the caller is supposed to be responsible for mutation
waypoint.heading = update_waypoint_heading(new_observation, waypoint);
We had a bug where we changed the function but did not change the caller. So we ended with
update_waypoint_heading(new_observation, waypoint);
Where update_waypoint_heading started to return the new heading. But it never got set to the waypoint. This was also perfectly legal for the compiler.
Is it possible to declare a parameter as mutant (like the opposite of const), where it will throw a compiler error if it does not get mutated. So that I can catch these cases at compile time
No, and it wouldn't make much sense either.
You pass an argument into a function, and want a keyword to mandate that the calling scope then assigns the result of that function into some part of the same thing you passed as an argument?
This is very convoluted.
If a function returns a result that ought to be used, then that is documented by its return type. If it modifies its by-reference arguments, then that should also be documented. Do not switch from one to the other after you've already got code using that function!
HOWEVER! There is the nodiscard attribute which will prevent the result of calling the function from simply being, well, discarded. That would have flagged this case up, and may be what you're really looking for.
You'll need a nice C++17 compiler to use it.
I still think this is a bit leaky, though. It's not up to your function to decide what the calling scope does with its result. Just don't change function semantics! Write a new function with a new name if you need to. "Update" is no longer a good descriptive name for what it does anyway.
This might be a pretty nooby question, but I wasn't able to figure it out by myself.
So, I am trying to pass a lambda into the following function:
wiringPiISR(int pin, int mode, void (*function)())
... what results in this:
wiringPiISR(Pin::BELL, INT_EDGE_RISING, [] {});
... and seems to work, so I obviously can use a lambda instead of pointing to a function.
But what I actually want to do is something like that, with capturing this to access the function onInterrupt(Pin pin) in the outer context:
wiringPiISR(Pin::BELL_1, INT_EDGE_RISING, [this] {
onInterrupt(Pin::BELL_1);
});
wiringPiISR(Pin::BELL_2, INT_EDGE_RISING, [this] {
onInterrupt(Pin::BELL_2);
});
... what results in this error message:
No matching function for call to wiringPiISR
I'm not very experienced in using c++-lambdas, I know closures from many other languages, but they obviously seem to work different in c++. This capturing seems to modify the signature of the closure, but I have no idea how to fix this, or even if there is a possible solution without pointing to an "actual" function.
Thank you in advance
C++ lambdas are only convertible to function pointers if there is no capture (and you are capturing this as stated).
Also refer to the draft C++11 standard section 5.1.2:
The closure type for a lambda-expression with no lambda-capture has a
public non-virtual non-explicit const conversion function to pointer
to function having the same parameter and return types as the closure
type’s function call operator.
As a solution, you could use std::function instead of the function pointer.
I am reading some VC++ code and see some usage of this function annotation _Function_class_(name).
According to MSDN:
The name parameter is an arbitrary string that is designated by the user. It exists in a namespace that is distinct from other namespaces. A function, function pointer, or—most usefully—a function pointer type may be designated as belonging to one or more function classes.
However, I still couldn't understand in what scenario this should be used, and what exactly it means to a function. Can someone please explain a bit more?
Thank you
This annotation allows you to restrict the set of functions that may be used in a given context. Generally, when using pointers to functions and references to functions, you can bind those pointers and references to refer to any function that has the correct type.
There may be cases where you want only a restricted set of functions of that type to be usable in a given context, or you may want to ensure that someone really, really means to use a particular function in that context. For example, if you take a pointer to a callback function, and there are restrictions on what may be done inside of that callback, you might use this attribute to help developers to think about those restrictions when passing new functions as callbacks.
Consider the following example: f is annotated as being of the special_fp_type class of functions. g is of the same type, so it is usable in the same contexts as f, but it is not annotated as being of the special_fp_type class of functions:
#include <sal.h>
typedef _Function_class_(special_fp_type) void (*special_fp_type)();
void _Function_class_(special_fp_type) f() { }
void g() { }
void call_special_function(special_fp_type) { }
int main()
{
call_special_function(f);
call_special_function(g);
}
If you compile this with /analyze, you'll get a helpful warning for the usage of g here, telling you that it was not part of the expected class of functions:
warning C28023: The function being assigned or passed should have a _Function_class_ annotation for at least one of the class(es) in: 'special_fp_type':
Frequently, when only one function class is in use, this is caused by not declaring a callback to be of the appropriate type.
There are situations that I have to choose local classes over lambda when overloading operator() is not enough or when I need virtual functions or something else.
um.. for example:
I need a object that captures local variables, and holds more than one functions, which are, unfortunately of same signature.
Overloading lambdas can solve such problem if the functions are of different signatures. And I think this is one common problem since there is the lambda-overloading trick.
I need a object that capture local variables and inherits some other class or have member variables.
This is something happens everyday in the java world. Dynamic polymorphism has its usefulness, at least sometimes.
What I'm doing now, is defining some helper macros like these:
#define CAPTURE_VAL(Var) decltype(Var) Var
#define CAPTURE_REF(Var) decltype(Var) &Var
#define INIT_CAPTURE(Var) Var(Var)
And put them into the local class:
struct Closure
{
Closure(CAPTURE_VAL(var1), CAPTURE_REF(var2)) : INIT_CAPTURE(var1), INIT_CAPTURE(var2)
{
}
int foo()
{
return some_expression;
}
private:
CAPTURE_VAL(var1);
CAPTURE_REF(var2);
} closure(var1, var2);
And this is ugly.
I have to refer a same variable three times.
I have to give the class a name for ctor.
I have to give a variable name for the closure, though I think this cannot be helped under the current standard.
At least in VC++11, captured variables of a lambda are private, so I cannot simply inherit the lambda class. And inheriting lambda class, at least in VC++11, needs a variable (or maybe some other placeholders for the evaluation) for the lambda, which is ugly.
And I think I don't even know if the standard allows me to capture the type of local variables in a local class this way...
Tested on GCC 4.6, local variable's type can't be captured as in VC++. And captured variables are not exposed as in VC++. LOL
Ah, my bad. I forgot to turn C++11 on. This works fine on G++. But lambda types can't be inherited, and captured variables are still not exposed.
Not quite fine... Have to leave -fpermissive on. Or G++ think the member variables conflict with local variables used in decltype().
I've been wandering why C++ has chosen such a high-leveled lambda for closure instead of more generic local class that can capture local variables.
This is going to be more than fits into a simple comment on your question, so I'll make it an answer.
There are indeed cases where you want something else and more complex than a simple functor or lambda. But these cases are very different and diverse, there is no "one fits all" solution, especially none that fits into a few lines and that will not blow the scope of a single function.
Creating complex behavior on the fly locally inside a function is not a good idea in terms of readability and simplicity, and most surely will violate the SRP for the function.
In many cases, if you have to write more than a single operator(), that means you will want to reuse the code you have written, which cannot be done if it is inside a local class.
Meaning: In most cases it will be the best solution to write a proper class, outside the function, with proper constructors and so on.