[C++] How to tell function which part of struct to use

Pages: 12
As an explanation, I'll use a very simple example.

Say I have a structure defined as such:
1
2
3
4
struct data{
  char c;
  int x;
};


And I want to create a function to print either c or x. However, I don't want to just use a switch or something to figure this out, I want to reference which part I'm outputting.

Now here's the twist
 
vector<data> dataList;


I need to access element x or c in the vector, but all I pass is the vector and which element, so that I might have something like:
1
2
3
void (vector<data> x, DataType i){
  cout << x[0].i;
}


So now, if I pass either x or c (someway), I can output one of them. Does that make sense, and can it be done?

Thanks.
closed account (N36fSL3A)
I don't understand.

If you wanted to just pass the element of a vector, why not just make a function like this?

1
2
3
4
5
6
7
8
9
10
11
12
13
vector <Data>myvector;

void yourFunction(Data dat)
{
    // code
}

int main()
{
    yourFunction(myvector[0]);
    
    return 0;
}


So now, if I pass either x or c (someway), I can output one of them. Does that make sense, and can it be done?

I'm trying to figure out if you mean the struct member or the vector
I would give the function the vector, and the function would then loop through the vector (Yes, I know I didn't put a loop) printing element i. However, i could really be either x or c.

So when I say
cout << dat[index].i << endl;
That could be either of the following:
1
2
3
cout << dat[index].x >> endl;
// OR
cout << dat[index].c >> endl;


Which one i points to is based on what is passed to the function.
Last edited on
closed account (N36fSL3A)
Or you could just do it once, then loop through the vector and in the for loop call the function for each element.
I'm pretty sure this cannot be accomplished in C++ or any other strong typed language. I've only ever seen this functionality in scripting languages like Python.

There might be a way to simulate it with templates and some very nasty pointer math... but I'm hesitant to even suggest it because it's so ugly.


EDIT:

Here's my idea, untested. Again I don't recommend this and am just showing it because I find it interesting. I would strongly suggest you reconsider whatever it is you're trying to do and come up with a different way to do it.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <cstdlib>  // <- need stdlib for offsetof()

template <typename T>
void yourfunction(const std::vector<data>& d, size_t offset)
{
    std::cout << *static_cast<const T*>(  static_cast<const char*>(&d[0]) + offset ) << std::endl;
}

//.....
// usage:

std::vector<data> v;
// assume 'v' populated here

yourfunction<int>(v,offsetof(data,x));  // to print 'x' as an 'int'
yourfunction<char>(v,offsetof(data,c));  // to print 'c' as a 'char' 
Last edited on
Well, how would you suggest I sort a vector (End goal) based on the values of certain element inside the structure, so that at one point in the program, I might sort by c, and at another point, I might sort by x? Do I just have to create a function for each element? Even though the code will look the exact same except for it being .c and .x?
You could have the second parameter be an int/unsigned whose value indicates which data member to sort by. (Probably a lame way to do so)
Well, in that case, then I'd still have nearly identical code inside of the if statements, which is what I was trying to prevent. It would be cleaner code to just have separate functions, considering that will be using different data types.
closed account (N36fSL3A)
Wait, I think I'm understanding this. You want to return 2 different types for 2 different functions?

In that case you could just have overloaded functions.

1
2
3
4
int functionForX(std::vector);
char functionForC(std::vector);

// The compiler will determine which one to use based on the data type. 
Do you mean something like this?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <iostream>
#include <vector>

using namespace std;

struct data{
	char c;
	int x;
};

void printfunctx(vector<data> s, int index)
{
	cout << s[index].x << endl;
}

void printfunctc(vector<data> x, int index)
{
	cout << x[index].c << endl;
}

int main()
{
	vector<data> Dat;
	Dat.push_back(data()); 
	Dat.push_back(data()); 
	
	Dat[0].c = 'y';
	Dat[0].x = 24;
	
	Dat[1].c = 'n';
	Dat[1].x = 2;
	
	printfunctx(Dat, 0);
	printfunctc(Dat, 0);
	printfunctx(Dat, 1);
	printfunctc(Dat, 1);
	
	return 0;
}
Well, how would you suggest I sort a vector


Oh jeez, this is for sorting?

You can specify your own routine to sort by. If you want to sort by different values, just give a different routine.

http://www.cplusplus.com/reference/algorithm/sort/

See the "custom" version.

EDIT:

example (with C++11 lambdas):

1
2
3
4
5
6
7
// sort by 'c':
std::sort(  yourvector.begin(), yourvector.end(),
    [](const data& a, const data& b) { return a.c < b.c; } );

// sort by 'x':
std::sort(  yourvector.begin(), yourvector.end(),
    [](const data& a, const data& b) { return a.x < b.x; } );

Last edited on
Oops, missed the sort part. Thought he was just trying to figure how to use structs with vectors and how to print each one of the members.
Disch, I know that exists. Essentially, I'm trying to not have neatly identical code. BHX just gave a perfect example of what I was hoping to avoid. The functions are identical, save a few letters. But if that's what I have to do, I guess I have to. I was just hoping there was some way to not do it that way.
Yeah, I'm not sure if there is a way to do it, unless you add a third parameter to use an if statement to compare.

1
2
3
4
5
6
7
8
9
10
void printfunct(vector<data> s, int index, int check)
{
        if(check == 0)
             cout << s[index].c << endl;
        if(check == 1)
             cout << s[index].x << endl;
}

printfunct(Dat, 0, 0);  
printfunct(Dat, 0, 1);
Last edited on by closed account z6A9GNh0
Disch, I know that exists. Essentially, I'm trying to not have neatly identical code


I'm not sure I see the reason for wanting to avoid this. In my example, the sort routine is literally a single comparison. It's no more redundant to write the sorting lambda than it is to specify which element you want to sort by. It's just more verbose.
Less code = easier to change if necessary.

The idea was that maybe I could pass something that would say which element i pointed to. It would seem not, and now I know. I appreciated everybody's help and input.
closed account (N36fSL3A)
Sorry, I couldn't clearly understand the question.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//Assuming this is a struct only for holding multiple data types
struct data{
   char c;
   int I;
   char operator char() ()const{return c;}
   int operator int() ()const{return I;}
};

template<typename T>
void sortbytype(vector<data>& tosort, T dummy){
   sort(tosort.begin(), tosort.end(),
      [](const data& d1, const data& d2){
         return
            static_cast<decltype(dummy)>(d1)
            < static_cast<decltype(dummy)>(d2)
         ;
      }
   );
}


Pretty silly, and I don't even know if it would work.
Last edited on
I think I'll keep it clean, and just use functions. At least until I can fully understand that. :)
@Daleth:
I may be wrong but do you really need the dummy? Couldn't you just pass the type as a template parameter? Also I think it would be safer to have those operators private and either friend sortbytype or have it as a member.
Pages: 12