const function with functor modifying object - c++

If we consider the following method, I had the impression that bar can not modify this (i.e. its instance of Foo).
struct Foo {
int i;
// var shall not modify the respective instance of Foo, thus "const"
void bar(std::function<void(int)> func) const {
func(3);
}
};
However, the following is possible:
void anothermethod() {
Foo f;
f.bar([&](int x){f.i = 3;}); // modify Foo.i "within" Foo::bar const. Dangerous?
}
I see that the method bar is not "directly" modifying the value i of its instance, but its doing so "indirectly" via the given parameter func.
So here my question: Is it dangerous to do such things (i.e. passing a function that modifies the object into a const method of the respective object)?

bar didn't modify i, your lambda did.
Essentially you grabbed a reference to i from outside the class and stuffed that into the lambda. Then you called bar. bar made no mention of the members of itself, it only called some arbitrary (non-member, so the const-ness of bar is irrelevant) function that it was provided.
The flaw you have here is that one can get a hold of a reference to the i member from outside the struct. Which means that anybody else can fiddle with i. Make i private and see how well the above works for you.

Related

Is it possible to extract the capture list of a lambda?

From this link here I understand that inorder to pass a lambda we need to pass the method as a parameter and to store it in a std::function type. In such case, is it possible to extract the parameters from a capture list of a lambda?
example
struct foo
{
std::vector<int> t = {1,2,3};
};
void funct(std::function<void()> func)
{
func(); //This works fine . Can I extract the object foo from this lambda ?
}
int main()
{
foo a;
a.t.push_back(45);
funct( [a](){ std::cout << "New value is " << a.t[3] ; } );
}
In order to get access to the object stored in a std::function object, you must use the std::function::target<T> template function. In this case, T is the actual type of the object you passed to the function's constructor.
As it turns out, the type of a lambda is untype-able. That is, the standard requires that, whatever typename the compiler assigns it, it is a typename that you cannot enter on the keyboard. If you don't already have it (either directly or via type deduction on a value of that type), then there's nothing you can do to get it.
Now, you could do this:
template<typename T>
void funct(T func)
{
std::function<void()> stdfunc(func);
T *ptr_func = stdfunc.target<T>();
}
Of course, that's rather redundant, since you already have the lambda function's type.
However, even with the above code, you cannot access the capture variables of a lambda. Why? Because the standard doesn't say you can.
The short list of things you're allowed to do with lambda closures:
Copy/move construct them, assuming the types captured are copy/moveable.
Destroy them.
Call them with operator().
Convert them to a function pointer, but only if the lambda was capture-less (and non-generic).
The implementation is not required to allow you to access member variables of the lambda. And therefore, there is no standard way to do so. Even if the implementation made them public and named them the way they're named in your code (neither of which is required), the C++ standard does not guarantee that every implementation must do so.
I don't think you can. Because lambdas are equivalent to a class whose operator() has been overloaded. The captured parameters are actually private data members. In this example, your lambda equivalent to:
class _lambda {
public:
void operator()() const {
std::cout << "New value is " << a.t[3];
}
private:
foo a;
}
I don't think you can get access to a private member with friendship ungranted.

Passing arbitrary information for a functional parameter to use

In C++:
I have an object I'll call Foo.
Foo performs statistical operations on a supplied data set. The first step of the process involves a fitting function, and a functional parameter can be supplied so that the user can specify the type of model being used.
The problem is that I now have a situation where the function parameter needs to have access to data that does not exist in Foo but rather in the object that is using Foo, which I will call Bar.
So Bar calls Foo to have Foo operate on Bar's data. Bar has a specific function it wants to use as the functional parameter but this function requires information specific to Bar.
I don't want to pass Bar because if I code Foo up to receive Bar, then every time I have a new object that needs additional info passed to Foo, I will have to adjust the Foo class to accept that object.
I don't want to modify the functional parameter input in Foo because then I'll have to modify the functional parameter input for every new usage case as well.
I considered using a base class I'll call StandardFunc. Then, via virtual methods, Bar could create an object called ModifiedFunc that derives from StandardFunc. It could override the StandardFunc's function and also supply the additional info as class parameters. This doesn't work either because to avoid slicing I have to type-cast ModifiedFunc to StandardFunc. This means that inside Foo I have to change the type-cast line for every new object name.
Can someone please point me in the right direction for how I can allow users to pass either a functional parameter alongside arbitrary parameters the function requires without having to recode the Foo class for every different usage case? I'm really stuck on this.
EDIT: pseudo code example:
class Foo
{
void processHandler(function)
void process();
void process(function);
void theUsualFunction(vector); //the default function used by process
vector vec;
};
void Foo::process()
{
processHandler(theUsualFunction);
}
void Foo::process(function f)
{
processHandler(f)
}
void Foo::processHandler(function f)
{
f(vec)
//do other stuff to vec
}
void Foo::theUsualFunction(vector v)
{
//default vec processor
}
class Bar
{
int x;
int y;
vector vec;
void theModifiedFunction(vector);
void callFooToProcess();
};
void Bar::theModifiedFunction(vector v)
{
//process v, but in a way that requires x and y
}
void Bar::callFooToProcess()
{
Foo foo;
foo.setVector(vec);
process(theModifiedFunction);
}
So this code is kind of an example of what I want to achieve, but it doesn't work as written. The reason is because I have no way of getting Bar::x and Bar::y to the function Foo::processHandler(function) without modifying the arguments for Foo::processHandler, and I don't want to do that because then every new class like Bar and every new theModifiedFunction that requires different data will require me to rewrite the arguments for processHandler.
This doesn't work either because to avoid slicing I have to type-cast ModifiedFunc to StandardFunc.
Slicing only occurs if you pass the argument by value. You should pass it as a pointer, that's how polymorphism is supposed to work.
Also, you can keep passing the argument by value if you make your class a template:
template<class Func>
class Foo {
void doStuff(Func func) {
...
}
}
Keep in mind though, that in this case Func has to be known at compile-time.
Although there may be other ways of handling this situation, I would suggest considering to have Bar contain Foo. This is called a has-a relationship [wiki]. The advantage of this is that you can use Foo as-is without modifying anything within Foo, as well as Bar need not pass around its private data. Hope the following code snippet would help you to understand the concept.
public class Bar
{
private Foo myFoo;
private int myInfo;
void a()
{
myFoo.doStuff(myInfo);
}
}

What does operator()() define?

I'm sorry if this question gets reported but I can't seem to easily find a solution online. If I override operator()() what behavior does this define?
The operator() is the function call operator, i.e., you can use an object of the corresponding type as a function object. The second set of parenthesis contains the list of arguments (as usual) which is empty. For example:
struct foo {
int operator()() { return 17; };
};
int main() {
foo f;
return f(); // use object like a function
}
The above example just shows how the operator is declared and called. A realistic use would probably access member variables in the operator. Function object are used in many places in the standard C++ library as customization points. The advantage of using an object rather than a function pointer is that the function object can have data attached to it.

Some questions about C++ from a C# developer [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
I have some questions about C++ from a C# developer.
For a few days I have been looking at some C++ code, and I have the following questions:
When do use Foo::, Foo. and Foo-> ?
When do I use a real constructor and when just String a; (sometimes I need to do something like String a("foo");)
What is the difference between these signatures: int foo(int a) and int foo(int &a)?
:: is used either to explicitly specify a namespace (std::string, for example, for the string class in the namespace std), or for static members of a class.
. is used much as in C#, to refer to a member of a class.
-> is used with pointers. If p is a pointer to an object obj, then p->x has the same meaning as obj.x.
when do i use a real constructor and when just String a; (sometimes i need to do something like String a("foo");)
When you need to. String a is roughly equivalent to C#'s a = new String() (with the caveat that if String is a non-POD type, it may contain uninitialized members.)
If you need a initialized to a specific value, you do that. (either with String a("foo"), or with String a = "foo")
where is the difference between these signatures: int foo(int a) and int foo(int &a)?
The & denotes a reference. It's not quite a C# reference, but there are similarities. In C#, you have value types and reference types, and reference types are always passed by reference.
In C++, there's no such distinction. Every type can be passed by value or by reference. The type T& is a reference to T. In other words, given the following code:
void foo(int& j);
void bar(int j);
int i = 42;
foo(i);
bar(i);
foo will get a reference to i, which means it it can modify the value of i.
bar will get a copy of i, which means that any modifications it makes will not be reflected in i.
You often use const T& (a reference to const T) as a way to avoid the copy, while still preventing the callee from modifying the object.
1: Assuming you which to call a method
Foo::theMethod(...)
is for example used when calling a static method of a class Foo
Foo.theMethod(...)
is when you have an object named Foo
Foo->theMethod(...)
is when you have a pointer to a object of named Foo
2:
String a;
calls the default constructor that takes no arguments
String a("foo")
calls a overloaded constructor
3:
int foo(int &a)
takes a reference to an integer, so within the method you are able to manipulate a.
int foo(int a)
makes a copy, manipulating it wont have any effect of the actual parameter passed in after leaving the method.
Question 1:
It depends on what Foo is. The :: operator is called the scope
resolution operator; the operand on the right must be a namespace or a
class, and the operand to the left a member of the namespace or class.
If Foo is a class, Foo:: can be used to access a static member, or
from within a member of a derived class, to access the member of the
base class: e.g.:
class Foo
{
public:
virtual void f();
static void g();
};
int h()
{
Foo::g();
}
class Derived : public Foo
{
public:
virtual void f()
{
Foo::f(); // Call function in base class...
}
}
It's often used to access namespace members as well, e.g. std::cout
(the cout object in namespace std).
The . operator is a member access operator, and requires an object (or
a reference to an object) as the left hand operand. Thus (using the
above definitions):
Foo obj;
obj.f();
void i( Foo& rFoo )
{
rFoo.f();
}
It can also be used to access static members, if you have an instance:
Foo obj;
obj.g();
The -> is very much like the . operator, except that it takes a
pointer to an instance, rather than an instance, and (very importantly)
it can be overloaded. Thus:
Foo* obj;
obj->g();
// And if Ptr is a user defined type with an overloaded
// `operator->` which returns a Foo*
Ptr obj;
obj->g();
Again, you can also use this syntax to access a static member, if you
have a pointer to an object.
Question 2:
The definition String a; calls a real constructor. You use String
a; when you want the default constructor; the one with no parameters.
You use String a( "foo" ); when you want the constructor which takes a
char const* (or a char const (&)[4], but that's highly unlikely, since it
will only work for a string literal with exactly three characters).
In general, when defining variables:
String a; // default constructor...
String a1(); // NOT what it looks like: this is a
// function declaration, and not the
// definition of a variable!!!
String b( x, y, z ); // constructor taking x, y and z as arguments...
String c = x; // implicitly convert `x` to String, then
// copy constructor.
The last form is a bit tricky, since the copy constructor may be (and
almost always is) elided, but the legality of the program is defined by
the rule above: there must be a way of implicitly converting x into a
String, and String must have an accessible copy constructor.
In other contexts, e.g. new String(), the form with empty parameters
can be used for "value construction", which is the default constructor
if there is a user defined one, otherwise zero initialization.
Question 3:
The first is pass by value, and passes a copy of the argument to the
function. The second is pass by reference, and passes a reference
(which behaves sort of like a hidden, automatically dereferenced
pointer) to the function. Thus:
void f( int a )
{
++ a; // Modifies local copy, has no effect on the argument.
}
void g( int& a )
{
++ a; // Modifies the variable passed as an argument.
}
Note that in the first case, you can pass an arbitrary expression; in
the second, you must pass something called an lvalue—that is,
something you can access afterwards using a similar expression (a named
variable, or a dererenced pointer, or an element in a named array,
etc.).
String a : construct an empty String object
String a("foo") : construct a String object initalized to "foo"
int foo(int a) : pass a by value/copy to foo. Inside foo if you modify a , a will not be impacted outside foo
int foo(int& a) : pass a by reference inside foo. If you modify a , a will also be modify once foo ended
Foo:: - Static methods
Foo. - Instance Methods when you have a stack object instance. (MyObject obj)
Foo-> - Instance methods when you have a object pointer. (MyObject* pObj = new MyObject())
Whenever you need to pass some value to the constructor.
int& is a reference to an int. Any changes to a within the method will affect a outside the method. (Equivalent to ref in C#)

Declaring C++ member function as static const yields errors

I have the following class interface:
class Test
{
public:
Test();
static void fun() const;
private:
int x;
static int i;
};
Test.cpp contains fun()'s implementation:
void Test::fun() const
{
cout<<"hello";
}
it is giving me errors... modifiers not allowed on static member functions
What does the error mean? I want to know the reason why I am not able to create a function which is static as well as const.
void fun() const;
means that fun can be applied to const objects (as well as non const).
Without the const modifier, it can only be applied on non const object.
Static functions by definition need no object.
A member function being const means that the other non-const members of the class instance can't be called.
A free function isn't a member function, so it's not associated as to a class or class instance, so it can't be const as there is no member.
A static function is a free function that have it's name scoped inside a class name, making it always relative to a type, but not associated to an instance of that type, so there is still no member to get access to.
In those two last cases, there is no point in having const access, as there is no member to access to.
Static functions work without an instance, whereas const guarantees that the function will not change the instance (even though it requires an instance).
It may be easier to understand if you see the translated code:
static void fun();
at the end of the day is translated to a function that takes no argument, namely
void fun();
For the other example,
void fun() const;
at the end of the day is translated to a function of the form
fun(const Test& self)
Thus, static void fun() const has two contradictory meanings.
BTW: This translation occurs for all member functions (const or not)
i answered this a few hours ago here: Why we need to put const at end of function header but static at first?
(SO system is not happy with my response. automatically converted to comment)
Perhaps it would help to have a simple code example.
class Foo {
public:
static void static_function();
void const_function() const;
};
// Use of static function:
Foo::static_function();
// Use of const function:
Foo f;
f.const_function();
The key difference between the two is that the const function is a member function -- that is, it is invoked on instances of the Foo class. That means you first need to instantiate an object of type Foo, and then that object acts as the receiver of the call to const_function. The const itself means that you won't modify the state of the object which is the receiver of that function call.
On the other hand, a static function is essentially a free function, where you can call it without a receiving object. Outside the scope of the class where it's defined, however, you'll need to qualify it using the class name: Foo::static_function.
This is why it doesn't make sense to have a function which is both static and const, as they're used in entirely different contexts. There's no need to worry about modifying the state of any object when invoking a static function because there is no receiving object -- it is simply invoked like a free function.
Because a static const function of a class does not make sense. const means that a thing (object/variable) stays the same. Static means that a thing object etc stays the same in that context.