So, for an assignment I have to write a template function that will successfully swap two values of any type. I also have to verify that pointers can be used by this function as well. Apparently, thorough output will demonstrate swapping of the pointers, but not swapping of the values they point-to.
I have a general idea of how to start, but not where to go afterwords.
Here's what I have so far.
template <typename T>
void swap(T*& first, T*& second)
{
T* a = nullptr;
a = first;
first = second;
second = a;
std::cout << first << " " << second << " ";
}
I've got the function prototype, but don't know what to do from here, any suggestions on how to call this function and if it would actually provide me the desired output?
Here's my main
int main()
{
swap(10, 20);
system("pause");
}
Thanks!
Your template function wants pointers to T as parameters. Your code
int main()
{
swap(10, 20);
system("pause");
}
doesn't call it with pointers but integer literal values. What you should use to call your function is
int main() {
int var1 = 42;
int var2 = 15;
int* pvar1 = &var1;
int* pvar2 = &var2;
swap(pvar1,pvar2);
}
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 << " ";
}
}
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;
}
Can someone tell me if my understanding is right ? can someone tell me if the code below is for reference to pointers ?
# include <iostream>
using namespace std;
//function swaps references,
//takes reference to int as input args and swap them
void swap(int& a, int& b)
{
int c=a;
a=b;
b=c;
}
int main(void)
{
int i=5,j=7;
cout<<"Before swap"<<endl;
cout<<"I:"<<i<<"J:"<<j<<endl;
swap(i,j);
cout<<"After swap"<<endl;
cout<<"I:"<<i<<"J:"<<j<<endl;
return 0;
}
You can create a reference to a pointer like this.
int i, j;
int* ptr_i = &i; //ptr_i hold a reference to a pointer
int* ptr_j = &j;
swap(ptr_i, ptr_j);
Function should be,
void swap(int*& a, int*& b)
{
//swap
int *temp = a;
a = b;
b = temp;
}
Note that:
a is the reference for the pointer, ptr_i in the above example.
*a dereferences what ptr_i point to, so you get the variable the
pointer, ptr_i is pointing to.
For more refer this.
In order to modify passing variables to a function, you should use reference (C-style pointers could also be a choice). If your objective is to swap pointers (in your case, addresses of the int variables) you should use reference to pointers and also pass to your swap function pointers (addresses of your int variables)
# include <iostream>
using namespace std;
void swap(int* &a, int* &b)
{
int* c=a;
a=b;
b=c;
}
int main(void)
{
int i=5,j=7;
int * p_i = &i;
int * p_j = &j;
cout << "Before swap" << endl;
cout << "I:" << *p_i << "J:" << *p_j << endl;
swap(p_i,p_j);
cout << "After swap" << endl;
cout << "I:" << *p_i << "J:" << *p_j <<endl;
return 0;
}
I would like to supplement everybody's answers with the standard conforming solution. It is good to know hot things like these work, but I find it better to use std::swap. This also has extra specializations a for containers, and it is generic for any type.
I know that this doesn't answer your question, but it is good to at least know that the standard is there.
I want to access the vector in the "manipulatevector" function below the same way as i access an array with vector[i] and not vector->at(i) in the code below. I have tried to pass the vector directly, and not a pointer as can be done with arrays. But this seem to corrupt the program. Any ideas how this can be achieved? Im new to using the std library, as i mostly have experience from C.
#include <vector>
#include <iostream>
#define vectorsize 5
struct st_test {
int ii;
float dd;
};
void manipulatevector(std::vector<struct st_test> *test) {
test->resize(vectorsize);
for(int i=0;i<vectorsize;i++) {
test->at(i).dd = i*0.4f;
test->at(i).ii = i;
}
}
void manipulatearray(struct st_test test[vectorsize]) {
for(int i=0;i<vectorsize;i++) {
test[i].dd = i*0.4f;
test[i].ii = i;
}
}
void main() {
std::vector<struct st_test> test1;
manipulatevector(&test1);
struct st_test test2[vectorsize];
manipulatearray(test2);
std::cout << "Vector" << std::endl;
for(int i=0;i<vectorsize;i++) {
std::cout << test1.at(i).dd << std::endl;
}
std::cout << "Array" << std::endl;
for(int i=0;i<vectorsize;i++) {
std::cout << test2[i].dd << std::endl;
}
}
Have you tried passing the vector as a reference?
void manipulatevector(std::vector<struct st_test> &test) {
test.resize(vectorsize);
for(int i=0;i<vectorsize;i++) {
test[i].dd = i*0.4f;
test[i].ii = i;
}
}
and
std::vector<struct st_test> test1;
manipulatevector(test1);
You can simply use (*test)[i] instead of test->at(i).
This is not actually the same behavior (at vs operator[]), but you are probably already aware of that.
Pass it as a reference instead of a pointer.
void manipulatevector(std::vector<struct st_test> &test) {
You then use . instead of ->, and things like the overloaded [] operator are usable.
Change the signature of void manipulatevector(std::vector<struct st_test> *test) to void manipulatevector(std::vector<struct st_test>& test). Then you can use the operator[] on the vector.
You can pass the vector by reference and use the [] operator:
void manipulatevector(std::vector<struct st_test>& test) {
test.resize(vectorsize);
for(int i=0;i<vectorsize;i++) {
test[i].dd = i*0.4f;
test[i].ii = i;
}
}
When you passed the vector directly, I presume you passed it by value:
void manipulatevector(std::vector<struct st_test> test) {
which meant any changes made inside manipulatevector() would not be seen by the caller. This would mean:
for(int i=0;i<vectorsize;i++) {
std::cout << test1.at(i).dd << std::endl;
}
would throw a std::out_of_range error, from test.at(i), as test1 would not have vectorsize elements, but zero elements. As there is no exception handling in main() this would have caused the program to crash.
There are different options here. You can pass the vector by reference, which is the simplest and cleaner in code:
void function( std::vector<type>& v )
Now, in some shops the style guide requires that if you are going to modify an argument you pass it by pointer as that makes it explicit at the place of call. In that case there are different options to call operator[]:
void function( std::vector<type> *v ){
(*v)[0] = .... // dereference first
v->operator[](0) = .... // explicitly cal the operator
std::vector<type>& vr =*v;
vr[0] = .... // create reference and use that
The first two are equivalent, with the first being arguably easier to read. The second is equivalent to the first one in that it dereferences the pointer and then accesses the operator, but you are explicitly giving a name to the reference, so it can be reused in the function without having to dereference in all uses. While this technically creates an extra variable, the compiler will most probably optimize the reference away.
I am not sure how to have a function that receives a class object as a parameter. Any help? Here is an example below.
#include<iostream>
void function(class object); //prototype
void function(class tempObject)
{
//do something with object
//use or change member variables
}
Basically I am just confused on how to create a function that will receive a class object as its parameters, and then to use those parameters inside the function such as tempObject.variable.
Sorry if this is kind of confusing, I am relatively new to C++.
class is a keyword that is used only* to introduce class definitions. When you declare new class instances either as local objects or as function parameters you use only the name of the class (which must be in scope) and not the keyword class itself.
e.g.
class ANewType
{
// ... details
};
This defines a new type called ANewType which is a class type.
You can then use this in function declarations:
void function(ANewType object);
You can then pass objects of type ANewType into the function. The object will be copied into the function parameter so, much like basic types, any attempt to modify the parameter will modify only the parameter in the function and won't affect the object that was originally passed in.
If you want to modify the object outside the function as indicated by the comments in your function body you would need to take the object by reference (or pointer). E.g.
void function(ANewType& object); // object passed by reference
This syntax means that any use of object in the function body refers to the actual object which was passed into the function and not a copy. All modifications will modify this object and be visible once the function has completed.
[* The class keyword is also used in template definitions, but that's a different subject.]
If you want to pass class instances (objects), you either use
void function(const MyClass& object){
// do something with object
}
or
void process(MyClass& object_to_be_changed){
// change member variables
}
On the other hand if you want to "pass" the class itself
template<class AnyClass>
void function_taking_class(){
// use static functions of AnyClass
AnyClass::count_instances();
// or create an object of AnyClass and use it
AnyClass object;
object.member = value;
}
// call it as
function_taking_class<MyClass>();
// or
function_taking_class<MyStruct>();
with
class MyClass{
int member;
//...
};
MyClass object1;
At its simplest:
#include <iostream>
using namespace std;
class A {
public:
A( int x ) : n( x ){}
void print() { cout << n << endl; }
private:
int n;
};
void func( A p ) {
p.print();
}
int main () {
A a;
func ( a );
}
Of course, you should probably be using references to pass the object, but I suspect you haven't got to them yet.
I was asking the same too. Another solution is you could overload your method:
void remove_id(EmployeeClass);
void remove_id(ProductClass);
void remove_id(DepartmentClass);
in the call the argument will fit accordingly the object you pass. but then you will have to repeat yourself
void remove_id(EmployeeClass _obj) {
int saveId = _obj->id;
...
};
void remove_id(ProductClass _obj) {
int saveId = _obj->id;
...
};
void remove_id(DepartmentClass _obj) {
int saveId = _obj->id;
...
};
holy errors The reason for the code below is to show how to not void main every function and not to type return; for functions...... instead push everything into the sediment for which is the print function prototype... if you need to use useful functions ... you will have to below.....
(p.s. this below is for people overwhelmed by these object and T templates which allow different variable declaration types(such as float and char) to use the same passed by value in a user defined function)
char arr[ ] = "This is a test";
string str(arr);
// You can also assign directly to a string.
str = "This is another string";
can anyone tell me why c++ made arrays into pass by value one at a time and the only way to eliminate spaces and punctuation is the use of string tokens. I couldn't get around the problem when i was trying to delete spaces for a palindrome...
#include <iostream>
#include <iomanip>
using namespace std;
int getgrades(float[]);
int getaverage(float[], float);
int calculateletters(float[], float, float, float[]);
int printResults(float[], float, float, float[]);
int main()
{
int i;
float maxSize=3, size;
float lettergrades[5], numericgrades[100], average;
size=getgrades(numericgrades);
average = getaverage(numericgrades, size);
printResults(numericgrades, size, average, lettergrades);
return 0;
}
int getgrades(float a[])
{
int i, max=3;
for (i = 0; i <max; i++)
{
//ask use for input
cout << "\nPlease Enter grade " << i+1 << " : ";
cin >> a[i];
//makes sure that user enters a vlue between 0 and 100
if(a[i] < 0 || a[i] >100)
{
cout << "Wrong input. Please
enter a value between 0 and 100 only." << endl;
cout << "\nPlease Reenter grade " << i+1 << " : ";
cin >> a[i];
return i;
}
}
}
int getaverage(float a[], float n)
{
int i;
float sum = 0;
if (n == 0)
return 0;
for (i = 0; i < n; i++)
sum += a[i];
return sum / n;
}
int printResults(float a[], float n, float average, float letters[])
{
int i;
cout << "Index Number | input |
array values address in memory " << endl;
for (i = 0; i < 3; i++)
{
cout <<" "<< i<<" \t\t"<<setprecision(3)<<
a[i]<<"\t\t" << &a[i] << endl;
}
cout<<"The average of your grades is: "<<setprecision(3)<<average<<endl;
}