I'm trying convert a object function to function pointer but can't get it, i've done something like this, simple example:
typedef struct
{
int v1;
int DoSome(int a)
{
return v1 * a;
}
} strx;
int main()
{
strx a; // instance...
a.v1 = 2;
std::function<int(strx* instance, int value)> DoSome = std::mem_fn(&strx::DoSome);
cout << DoSome(&a, 4) << endl; // 16 ok
int(*pDoSome)(strx* instance, int value) = (int(*)(strx*, int))std::mem_fn(&strx::DoSome); // syntax error
// ptr method...
pDoSome(&a ,4);
return 0;
}
and i have obtained something like:
main.cpp [Error] invalid cast from type 'std::_Mem_fn' to type 'int ()(strx, int)'
How i can do correctly the casting?
You can't. This is why std::function is more flexible than pointers to functions.
How i can do correctly the casting?
You cannot. Object pointers and function pointers are totally different concepts. Only nullptr can be used to initialize both types of pointers. Otherwise, they are not guaranteed to be compatible.
I suggest sticking with the std::function.
If you must have a function pointer, you have to use a non-member function or a static member function of a class.
E.g.
int doSomeFunction(strx* instance, int value)
{
// Use instance any way you please.
// ...
//
return 0;
}
int main()
{
strx a; // instance...
a.v1 = 2;
int(*pDoSome)(strx* instance, int value) = doSomeFunction;
// ptr method...
pDoSome(&a ,4);
return 0;
}
Related
I'm trying to write an example code for the following line of code:
int (*(*foo)(const void*))[3];
I got this code from here (at each refresh of the website you get a different piece of code and there is a finite set of them so by reloading a couple of times you will get my example). I wanted to see out of curiosity is it even possible to write some code that would make this line work.
Here is what I wrote so far:
#include<stdio.h>
#include<malloc.h>
int* goo(const void * ptr) {
int* ret = (int*) malloc(sizeof(int) * 3);
if (!ret)
return NULL;
for (int i = 0; i < 3; ++i)
ret[i] = i;
return ret;
}
int doo() { return 0; }
int main(void) {
//NOTE: Following 2 lines have syntax errors
int (*(*foo)(const void*))[3] = &goo;
int* values = foo(goo(doo));
for (int i = 0; i < 3; ++i) {
printf("%d", values[i]);
}
free(values);
return 0;
}
If I understood correctly, foo should be some function that receives as an argument another function and returns an int array of size 3. The problem is I don't know how to make foo in this case point to a function or even how to get the int array.
Is it even possible to make this line of code work?
If I understood correctly, foo should be some function
foo is a pointer to a function.
that receives as an argument another function
No, the parameter type of the function that foo points to must be a pointer to const void i.e. const void*. A pointer to void is an object pointer. It can point to an object of any type.
Functions are not objects, but on some systems, pointers to functions can be reinterpreted as pointers to void.
and returns an int array of size 3.
No; Return types cannot be arrays. The function must return a pointer to an array of 3 ints i.e. int(*)[3].
Is it even possible to make this line of code work?
Here is an example program that uses such foo. It doesn't make much sense, but that's because the goal is to use an obscure function pointer:
#include<iostream>
int arr[] {
1,
2,
3,
};
int (*goo(const void*))[3] {
return &arr;
}
int main() {
int (*(*foo)(const void*))[3] = &goo;
int (*values)[3] = foo(nullptr);
for (int i : *values) {
std::cout << i << " ";
}
}
We can greatly improve readability by introducing type aliases:
using IntArr3 = int[3];
using FooFun = IntArr3*(const void*);
IntArr3* goo(const void*) {
return &arr;
}
int main() {
FooFun* foo = &goo;
IntArr3* values = foo(nullptr);
for (int i : *values) {
std::cout << i << " ";
}
}
I can't figure out the following situation:
I've 3 classes:
AA.h
class AA
{
public:
AA();
static CC *i;
};
BB.h
class BB
{
public:
BB();
void static setI(CC *i);
};
CC.h
class CC
{
public:
CC();
};
AA.cpp
AA::AA(){}
CC *AA::i= nullptr;
BB.cpp
BB::BB(){}
void BB::setI(CC *i)
{
i = new CC();
cout<<i<<endl;
cout<<AA::i;
}
CC.cpp
CC::CC(){}
So I've a static pointe of type CC in the class A.
And i start the main in the following way:
int main(int argc, char *argv[])
{
BB::setI(AA::i);
return 0;
}
The output I get is
//0xaeed70
//0
So why AA::i does not equal i?
The parameter type of BB::setI is CC *i, the pointer itself is passed by value, i is copied from the argument. Any modification on i inside the function has nothing to do with the original argument AA::i.
What you want might be pass-by-reference, i.e.
void BB::setI(CC *&i)
{
i = new CC();
cout<<i<<endl;
cout<<AA::i;
}
In the expression i = new CC() variable i is local variable of function BB::setI which was initialized with the value of AA::i because you called function like BB::setI(AA::i);. Assigning any value to i will only change the value of this local variable, not the value of some other variable that has been used to initialize it when you called the function.
It's exactly the same situation as this smaller example:
int i = 0;
void setI(int x)
{
x = 1234;
cout << x << endl;
cout << i;
}
int main()
{
setI(i);
}
As you can see more clearly here, you're assigning a new value to the function's parameter.
This parameter is unrelated to AA's member.
Regardless of its type, if you want a function to modify an object, you need to pass it a reference (or pointer) to that object; you can't pass the object's value.
I am new to C++ and I started to reading a book on the topic. There is an exercise that says: "Declare a pointer to a function taking an int as argument and returning a pointer to a function that takes a char as argument and returns float". I ended up with this code:
#include <iostream>
using namespace std;
float func(char c) {
return 3.14;
}
float((*fun2(int))(char)) {
return &func;
}
int main() {
float(*fp)(char) = fun2(3);
cout << fp('c') << endl;
}
The question is: is it still appropriate in today's C++ programming. If so - are there any needed changes to be made to the code(applying new abstractions etc.)? Thanks.
You can declare a type alias:
using my_fp = float ( * )(char); // can work before C++11 with typedef
my_fp fun2(int){
return &func;
}
my_fp fp = fun2(0);
and / or completely automatic type deduction:
auto fun2(int) { // available in C++14
return &func;
}
// Use a suitable value in the call to fun2
auto fp{fun2(0)}; // available in C++11
Since the problem states to return a "function pointer", you are sort of stuck with slightly old syntax. However, if you aren't constrained by that and just want to return a function (and C interoperability isn't an issue), you can use std::function, which is a more modern, more general function type.
#include <functional>
// ...
std::function<float(char)> fun2(int) {
return &func;
}
The advantage to std::function (aside from looking prettier than the awkward float(*)(char) syntax) is that it can store function pointers, anonymous functions, and callable objects, whereas a traditional function pointer can only store pointers to global functions. So, for example, the following would be allowed.
struct Foo {
float operator()(char) {
// ...
}
};
std::function<float(char)> fun3(int) {
return Foo();
}
std::function<float(char)> fun4(int) {
return [](char) { return 1.0; };
}
Neither of fun3 nor fun4 would compile with a simple function pointer.
My literal version:
#include <iostream>
using my_pf = float(*)(char);
using my_ppf = my_pf(*)(int);
float func(char)
{
return 3.14f;
}
my_pf fun2(int)
{
return &func;
}
int main()
{
my_ppf ppf; // Your declaration:
// Pointer to a function taking an int as argument
// and returning a pointer to a function
// that takes a char as argument and returns float.
ppf = &fun2;
my_pf pf = ppf(3);
std::cout << pf('c') << '\n';
}
As alternative, there is the trailing return type (since C++11):
auto fun2(int) -> float(*)(char)
{
return &func;
}
I have an array of pointers declared as a class member like this:
class Bar
{
private:
static constexpr int SIZE = 10;
Foo* m[SIZE];
}
In one of my class methods, I would like to return a pointer (or preferably, a reference) to this array. The array has a known size at compile time, but I am keeping track of how many items I have put in there (it is a buffer of stuff).
What is the best way to return a reference to this array in C++11 ?
Here are the things I have tried:
GetArray(Foo* &f[], unsigned &size) const
I like the syntax because it makes it clear that the reference value is an array of pointers, but this gives a compiler error: Declared as array of references of type Foo*
GetArray(Foo** &f, unsigned &size) const
{
f = m;
size = mSize;
}
Gives me: Error: assigning to Foo **' from incompatible type Foo *const[10]. Casting mFoo to (Foo**) alleviates the error, but IMHO, this is not elegant.
Nobody posted an answer using std::array yet, it is a very simple replacement:
class Bar
{
std::array<Foo *, 10> m;
public:
std::array<Foo *, 10> & getArray() { return m; }
std::array<Foo *, 10> const & getArray() const { return m; }
};
This seems to me a lot simpler than the hoops you have to jump through to use your C-style array version.
To avoid code duplication you could typedef std::array<Foo *, 10> FooArray; .
The technique of having both a const and a non-const implementation is a common pattern for accessor functions which return a reference or a pointer. (It's not required if your accessor returns by value, of course).
I would seek to use a std::array or a std::vector in most cases. If you are determined to use a raw array then you could go this way with it:
typedef int Foo;
typedef Foo* (&FooPtrArrayRef)[10]; // to make the syntax less hairy
class Bar
{
private:
Foo* m[10];
public:
// First way without using typedef
Foo* (&getArray())[10]
{
return m;
}
// Nicer looking way with a typedef
FooPtrArrayRef getArrayByRef()
{
return m;
}
};
int main()
{
Bar b;
Foo* (&array)[10] = b.getArray();
std::cout << (sizeof(array) / sizeof(Foo*)) << '\n';
// Alternative using "size deduction"
Foo* (&array2)[sizeof(b.getArray()) / sizeof(Foo*)] = b.getArray();
std::cout << (sizeof(array2) / sizeof(Foo*)) << '\n';
// MUCH nicer using the typedef
FooPtrArrayRef array3 = b.getArrayByRef();
std::cout << (sizeof(array3) / sizeof(Foo*)) << '\n';
}
The syntax is pretty obscure though.
The benefits of this is approach is that it retains the full type information of the array you are passing by reference. The obscure syntax is necessary to avoid the type collapsing to a Foo**. By retaining the full type of the array you retain the ability to know its size at compile time using the sizeof() operator.
here's another approach that returns the array reference and the current size as a tuple:
#include <tuple>
#include <functional>
#include <algorithm>
#include <iterator>
#include <iostream>
struct Foo {};
using FooBuffer = Foo*[10];
class Bar
{
public:
Bar()
: _m { nullptr }
{
_m[0] = new Foo;
_m[1] = new Foo;
_items = 2;
}
~Bar() {
for(auto fp : _m)
delete fp;
}
std::tuple<FooBuffer&, size_t> getInfo() {
return std::make_tuple(std::ref(_m), _items);
}
private:
Foo* _m[10];
size_t _items;
};
int main() {
Bar b;
auto info = b.getInfo();
FooBuffer& buf = std::get<0>(info);
size_t items = std::get<1>(info);
for(Foo** p = buf ; p != buf + items ; ++p) {
std::cout << "Foo at " << std::hex << *p << std::endl;
}
return 0;
}
Please tell me the use of cascading, and when to use & before function like this int &func()
Where should i use that please give me small example, Thanks. I think it does return an address but no idea how to use.
You are about to commit a very common newbie mistake in C++, namely returning references to dead objects.
int &GetNumber()
{
int number = 123;
return number;
}
int main()
{
int x = GetNumber();
int y = x + 1;
}
Looks innocent but will create so-called undefined behaviour. This means that the program may do whatever it wants to - it will likely crash, or it will sometimes crash. In any case, it won't be safe. Your compiler may even warn you if you attempt to do this. The reason is that by the time GetNumber has finished, the local number is destroyed, and you end up with a reference to a destroyed object.
Usually, you will want to return a copy instead of a reference. This is the "normal" thing to do in C++:
int GetNumber() // now OK
{
int number = 123;
return number;
}
int main()
{
int x = GetNumber();
int y = x + 1;
}
Returning references is only safe when you know that the object referred to will continue to exist after the function returns. One example is when you are just returning a reference you were passed:
int &MyFunction(int &number)
{
// do something
return number;
}
This then allows you to chain functions:
struct Example
{
Example &MyFunction(Example &example)
{
// do something
return example;
}
};
int main()
{
Example example;
example.MyFunction(example).MyFunction(example).MyFunction(example);
}
Now, if this example strikes you as particularly useless (as it should), look at how the standard library handles << calls with std::ostream for a realistic use case.
std::cout << 1 << "a" << 0.5;
This syntax works because each operator<< call returns a reference to std::cout.
when to use &
Return by value vs return by reference
You usually return a reference when you want a caller to be able to change the original variable. Example can be returning elements of an array
struct Array
{
int values[ 10];
};
// Returns a reference to the nIndex element of rArray
int& Value( Array &rArray, int nIndex)
{
return Array.values[ nIndex];
}
int main()
{
Array myArray;
// Set the 10th element of sMyArray to the value 5
Value( myArray, 10) = 5;
assert( myArray.values[ 10] == 5); // OK
return 0;
}
Another example is returning reference to class member. You want to return original variable, not a copy of it. Consider:
struct A {
int something;
int f() { return something; }
int& g() { return something; }
};
int main()
{
A myA;
int i = myA.f(); // return by value: not original
// int but its copy with same value
i = 200;
assert( myA.something == 200); // fail
return 0;
}
but:
int main()
{
A myA;
int& i = myA.g(); // return by reference: original
// variable is referenced by i now
i = 200;
assert( myA.something == 200); // OK
return 0;
}
Operator chaining
Operator chaining is made to allow for expressions like:
a = b + c + d;
or
std::cout << "this" << " and " << "this";
Usually there is choice between returning by value or by reference made by considering the meaning of the operator or independent factors like for example that std::istream and std::ostream are not copyable, so trying to return objects of those types by value is an error.