So, I am new to pointers/addresses and I have a generic function that prints the address of a variable passed to it as a parameter. However, in the following snippet why the addresses are different despite they belong to the same variable?
template <typename T>
void printAddressOf(T t)
{
std::cout << &t << std::endl;
}
int main(int argc, char **argv)
{
int x = 12;
printAddressOf(x);
std::cout << &x;
return 0;
}
The values that I get as an output are...
0x7ffee2c6f86c
0x7ffee2c6f89c
Can someone explain this behaviour why this happens?
Because the variables are not the same, the values are.
In your argument list for function printAddressOf(T t) you are not passing a reference to a variable. Instead you pass a copy. So a new variable T t is created in this scope.
Change the function to
template <typename T>
void printAddressOf(T& t)
{
std::cout << &t << std::endl;
}
And you will see that the address is the same
printAddressOf(x) 0x7ffee2c6f89c
std::cout << &x << std::endl; 0x7ffee2c6f89c
Related
A beginner's question I couldn't find answered online, likely because I don't know the terminology.
I want to call one of a list of procedures based on a computed index value. That is, given a '1', invoke firstProc(), '2' invokes secondProc() and so on.
All the procedures are void functions with no arguments.
I can implement that with switch/case, but what I'd prefer is something like:
void* action[2] {*firstProc, *secondProc};
(This compiles, but warns: invalid conversion from 'void (*)()' to 'void*')
and then later:
action[get_index()]();
The compiler objects that 'action' can't be used as a function.
This must be possible, right? I've tried several variations but I can't get past the use of the selected ('action[index]') as a function.
There are two equivalent ways to do what you want. The explanation is given as comments in the code snippets.
Method 1
#include <iostream>
void foo()
{
std::cout << "Hello";
}
void foo2()
{
std::cout << " wolrd!";
}
int main()
{
void (*a)() = foo;// a is a pointer to a function that takes no parameter and also does not return anything
void (*b)() = foo2;// b is a pointer to a function that takes no parameter and also does not return anything
//create array(of size 2) that can hold pointers to functions that does not return anything and also does not take any parameter
void (*arr[2])() = { a, b};
arr[0](); // calls foo
arr[1](); //calls foo1
return 0;
}
Method 1 can be executed here.
In method 1 above void (*a)() = foo; means that a is a pointer to a function that takes no parameter and also does not return anything.
Similarly, void (*b)() = foo2; means that b is a pointer to a function that takes no parameter and also does not return anything.
Next, void (*arr[2])() = { a, b}; means that arr is an array(of size 2) that can hold pointers to functions that does not return anything and also does not take any parameter.
Method 2
#include <iostream>
void foo()
{
std::cout << "Hello";
}
void foo2()
{
std::cout << " wolrd!";
}
int main()
{
//create array(of size 2) that can hold pointers to functions that does not return anything
void (*arr[2])() = { foo, foo2};
arr[0](); // calls foo
arr[1](); //calls foo1
return 0;
}
Method 2 can be executed here.
You need the correct syntax for your function pointer array. void(*func_ptr[])().
Example:
void func1() { std::cout << "Hallo" << std::endl; }
void func2() { std::cout << "World" << std::endl; }
// if you need a different signature for your functions like:
int func3(int n) { std::cout << "n1 " << n << std::endl; return n*2; }
int func4(int n) { std::cout << "n2 " << n << std::endl; return n*3; }
int main()
{
// array of function pointer which
// have no parameter and void as return value
void(*func_ptr[])()={ func1, func2 };
for ( unsigned int idx = 0; idx<2; idx++ )
{
func_ptr[idx]();
}
// array of function pointers with int return value and int as
// parameter
int(*func_ptr2[])(int)={ func3, func4 };
for ( unsigned int idx = 0; idx<2; idx++ )
{
std::cout << "retval: " << func_ptr2[idx](6) << std::endl;
}
}
I've stopped using function pointers (though they still can be useful).
I usually use std::function (and lambdas) when working with functions
Code for arrays of functions then look like this.
I used std::vector but std::array for fixed size should work fine too.
#include <vector>
#include <functional>
#include <iostream>
void some_function()
{
std::cout << "some function\n";
}
int main()
{
// std::function, abstraction of a function, function signature = template parameter, so void () is function returning a void, no parameters
// std::vector, runtime resizable array
// constructor : 4 time a lambda function printing out hello world.
std::vector<std::function<void()>> functions(4, [] { std::cout << "Hello World!\n"; } );
// easy syntax to assign an existing function to an index
functions[1] = some_function;
// replace a function in the vector with another one (lambda)
functions[2] = [] { std::cout << "booh\n"; };
// call function at index 0
functions[0]();
std::cout << "\n\n";
// or loop over all the functions and call them (classic for loop)
for (std::size_t n = 0; n < functions.size(); ++n) functions[n]();
std::cout << "\n\n";
// or loop over all the functions (range based for loop)
for (const auto& function : functions) function();
return 0;
}
I have a problem with the code that uses function pointer that takes shared_ptr argument.
Here is a sample code.
header.h
#include <functional>
#include <iostream>
template <class T> class FuncWrapper{
private:
void (*original_function)(T a);
public:
void setFunction(void *func);
void execFunction(T a, void *data);
};
template <class T> void FuncWrapper<T>::setFunction(void *func){
original_function = (void (*)(T))func;
}
template <class T> void FuncWrapper<T>::execFunction(T a, void *data){
FuncWrapper<T>* wrapper = (FuncWrapper<T>*)data;
std::cout << "inside wrapper " << *(a.get()) << std::endl;
wrapper->original_function(a);
}
main.cpp
#include <iostream>
#include <memory>
#include "header.h"
class ClassA{
public:
ClassA(std::shared_ptr<int> a){
FuncWrapper<std::shared_ptr<int>> *fw;
fw = new FuncWrapper<std::shared_ptr<int>>;
fw->setFunction((void*)&ClassA::print_int);
std::function<void(std::shared_ptr<int>)> g = std::bind(&FuncWrapper<std::shared_ptr<int>>::execFunction, fw, std::placeholders::_1, fw);
g(a);
delete fw;
}
private:
void print_int(std::shared_ptr<int> x) {
std::cout << "printing int" << std::endl;
std::cout << "given int " << *(x.get()) << std::endl;
}
};
int main(int argc, char * argv[]){
std::shared_ptr<int> x = std::make_shared<int>(10);
std::cout << "inside main " << *(x.get()) << std::endl;
ClassA *temp;
temp = new ClassA(x);
delete temp;
return 0;
}
Result
inside main 10
inside wrapper 10
printing int
Segmentation fault (core dumped)
I cannot figure out why it causes segmentation fault.
Changing std::shared_ptr<int> to int works just fine.
Therefore I assume that it has to do with owenership of shared_ptr, but I'm not familiar with smart pointers and I'm completely at loss.
I want to know
why it does not work
how to make it work
Limitations are
w/o changing print_int function itself
execute function within FuncWrapper<T>::execFunction
FuncWrapper<T>::execFunction has to be static
Otherwise, it is free to change. (inside ClassA constructor, inside main execFunction etc.)
The problem is not the shared_ptr, but mismatch between pointers to a function and a member function.
Your function wrapper expects a pointer to a function (void (*)(std::shared_ptr<int>)), but you provide a pointer to a member function (void (ClassA::*)(std::shared_ptr<int>)), which is different. An implicit leading argument of pointer to this is added to it.
This is how it really looks like:
// pointer to member function
void (*)(ClassA *ptr, std::shared_ptr<int>)
Your shared_ptr goes to the first argument and fortunately the application segfaults.
One of the solutions is to make the function print_int static.
class ClassA{
public:
ClassA(std::shared_ptr<int> a){
FuncWrapper<std::shared_ptr<int>> *fw;
fw = new FuncWrapper<std::shared_ptr<int>>;
fw->setFunction((void*)&ClassA::print_int);
std::function<void(std::shared_ptr<int>)> g = std::bind(&FuncWrapper<std::shared_ptr<int>>::execFunction, fw, std::placeholders::_1, fw);
g(a);
delete fw;
}
private:
static void print_int(std::shared_ptr<int> x) {
std::cout << "printing int" << std::endl;
std::cout << "given int " << *(x.get()) << std::endl;
}
};
But there seems to be another problem in your code. Function pointers should not be converted to object pointers (which void * is). Maybe change your setFunction this way:
void setFunction(void (*func)(T)) {
original_function = func;
}
More on that here
#include <iostream>
#include <utility>
template<typename T>
void f1(T&& t) // &&
{
if constexpr (std::is_function_v<typename std::remove_pointer_t<T>>)
std::cout << "function" << std::endl;
else
std::cout << "not a function" << std::endl;
}
template<typename T>
void f2(T& t) // &
{
if constexpr (std::is_function_v<typename std::remove_pointer_t<T>>)
std::cout << "function" << std::endl;
else
std::cout << "not a function" << std::endl;
}
void print(){}
int main()
{
f1(print);
f2(print);
return 0;
}
According to f1, print is not a function.
According to f2, print is a function.
Understanding why this is so would help understanding the && operator
In the both cases a function is passed by reference. And the both functions deals with lvalue reference to the function print.
Use
std::is_function_v<std::remove_reference_t<T>>
instead of
std::is_function_v<typename std::remove_pointer_t<T>>
You can also insert a statement like this in the both functions
std::cout << std::is_lvalue_reference_v<decltype( t )> << '\n';
to be sure that the functions deal with the lvalue reference to rpint.
Take into account that you need to include the header <type_traits>.
If you want that the functions would deal with function pointers then you need to use a call like this
f1(&print);
In this case the second function should be declared like
template<typename T>
void f2( const T& t);
Otherwise you may not bind a non-constant reference to rvalue.
Or call the function f2 like if you do not want to use the qualifier const.
auto p = print;
f2(p);
I know that I shouldn't overload a function for just parameters differ only in one of them passed by copy and the other by reference:
void foo(int x)
{
cout << "in foo(int x) x: " << x << endl;
}
void foo(int& x)
{
cout << "in foo(int& x) x: " << x << endl;
}
int main()
{
int a = 1;
foo(5); // ok as long as there is one best match foo(int)
foo(a); // error: two best candidates so the call is ambiguous
//foo(std::move(a));
//foo(std::ref(an)); // why also this doesn't work?
}
So a code that uses std::bind can be like this:
std::ostream& printVec(std::ostream& out, const std::vector<int> v)
{
for (auto i : v)
out << i << ", ";
return out;
}
int main()
{
//auto func = std::bind(std::cout, std::placeholders::_1); // error: stream objects cannot be passed by value
auto func = std::bind(std::ref(std::cout), std::placeholders::_1); // ok.
}
So std::ref here to ensure passing by reference rather than by value to avoid ambiguity?
* The thing that matters me: Does std::bind() implemented some wrapper to overcome this issue?
Why I can't use std::ref in my example to help the compiler in function matching?
Now that you know passing by value and reference are ambiguous when overload resolution tries to compare them for choosing a best viable function, let's answer how would you use std::ref (or std::cref) to differentiate between pass-by-value and pass-by-reference.
It turns out to be ... pretty simple. Just write the overloads such that one accepts a int, and the other accepts a std::reference_wrapper<int>:
#include <functional>
#include <iostream>
void foo(int x) {
std::cout << "Passed by value.\n";
}
void foo(std::reference_wrapper<int> x) {
std::cout << "Passed by reference.\n";
int& ref_x = x;
ref_x = 42;
/* Do whatever you want with ref_x. */
}
int main() {
int x = 0;
foo(x);
foo(std::ref(x));
std::cout << x << "\n";
return 0;
}
Output:
Passed by value.
Passed by reference.
42
The function pass the argument by value by default. If you want to pass by reference, use std::ref explicitly.
Now let's answer your second question: how does std::bind deal with this type of scenario. Here is a simple demo I have created:
#include <functional>
#include <type_traits>
#include <iostream>
template <typename T>
struct Storage {
T data;
};
template <typename T>
struct unwrap_reference {
using type = T;
};
template <typename T>
struct unwrap_reference<std::reference_wrapper<T>> {
using type = std::add_lvalue_reference_t<T>;
};
template <typename T>
using transform_to_storage_type = Storage<typename unwrap_reference<std::decay_t<T>>::type>;
template <typename T>
auto make_storage(T&& obj) -> transform_to_storage_type<T> {
return transform_to_storage_type<T> { std::forward<T>(obj) };
}
int main() {
int a = 0, b = 0, c = 0;
auto storage_a = make_storage(a);
auto storage_b = make_storage(std::ref(b));
auto storage_c = make_storage(std::cref(c));
storage_a.data = 42;
storage_b.data = 42;
// storage_c.data = 42; // Compile error: Cannot modify const.
// 0 42 0
std::cout << a << " " << b << " " << c << "\n";
return 0;
}
It is not std::bind, but the method used is similar (it's also similar to std::make_tuple, which has the same semantic). make_storage by default copies the parameter, unless you explicitly use std::ref.
As you can see, std::ref is not magic. You need to do something extra for it to work, which in our case is to first decay the type (all references are removed in this process), and then check whether the final type is a reference_wrapper or not; if it is, unwrap it.
I am trying to pass a member of class as argument to a function (not member method). The simple example of my intention would be like this.
template <typename ObjType>
void myOutput(ObjType* obj, ????)
{
std::cout << obj->???? << std::endl;
}
struct A
{
int a;
};
struct B
{
std::string b;
};
int main()
{
A A1;
B B1;
A1.a = 1;
B1.b = "something";
myOutput(&A1, A1::a);
myOutput(&B1, B1::b);
return 0;
}
So my question is what should i replace "????" with? I am not using C++11.
Thanks.
EDIT:
To clarify my intentions. The function myOutput doesn't really know the name of my member, and i do not want to use a function like memberToString() or something.
So the output should look like this for first call.
void myOutput(A* obj, ????)
{
std::cout << obj->a << std::endl;
}
and for the second
void myOutput(B* obj, ????)
{
std::cout << obj->b << std::endl;
}
If you know the member name at compile time, you can use a member pointer to refer to the member.
template <typename ObjType, typename MembType>
void myOutput(ObjType* obj, MembType memb)
{
std::cout << obj->*memb << std::endl;
}
This can then be called as such:
myOutput(&A1, &A::a);
myOutput(&B1, &B::b);
Naturally, you should ask yourself why it is you want to do this, and if it wouldn't be possible to simply pass A1->a or B1->b directly into the function as a single argument, instead.