Function of unknown or union type

Let's imagine a situation like this. We have a function that performs some sort of calculations. The result can be either 1,2 or 3. Depending on the result we want to return different values. Let's say if the outcome is 1, the return will be 1 (integer). For 2 it will be 2.1452 (float), and for three it will be 'A' (char). Therefore we cannot predict what type will be returned. I thought of using a union, but so far so unsuccessful. This is what I have for now (it won't compile):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
union myType {
	int number;
	float point;
	char letter;
};

myType fun ()
{
	int val=rand()%3+2;

	switch (val)
	{
	case 1:
		fun().number=1;
		return fun().number;
	case 2:
		fun().point=2.14;
		return fun().point;
	case 3:
		fun().letter='A';
		return fun().letter;
	}
}

My workaround (which I don't want to use) -depending on the situation- is to return int or float and then cast it, but as I said- I am seeking a solution without casting, because it's not always suitable.
I think what you're looking for is templates :)
What is your goal?

Your rand() function is returning values 2-4, not 1-3.
@ResidentBiscuit I think what you're looking for is templates :)

That's exactly what I was afraid of :-(

@LowestOne Your rand() function is returning values 2-4, not 1-3.

Just a typo ;) The idea remains.
The idea remains

It doesn't really make sense though. You have absolutely no way to know the difference between these things. 2.14 will be stored in memory as 0x4008f5c3, which you won't be able to differ from an integer 1,074,329,027.

You might as well just return a float always, with values 1, 2.14, or 65
Last edited on
The return type of a function shall be known at compilation time. You can return a union but you should declare one more data member of the union that will be point out what exactly data member of the union contains the result.

For example

1
2
3
4
5
6
7
8
9
10
struct Result
{
   enum { INT, FLOAT, CHAR } kind;
   union
   {
      int number;
      float point;
      char letter;
   };
};
Last edited on
I know I can always return a float and then cast it to whatever I want, but it's an exercise. Let's say that for some reason I can't force it to return float.

@ResidentBiscuit Could you write such a template? I'd like to step my game up :-D
Last edited on
@vlad from moscow Could you show a working example?
Working example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Result GetRandomValue()
{
    Result r;
    int Val = rand()%3;
    switch(Val)
    {
        case 0:
            r.kind = INT;
            r.number = 2;
            return r;
        case 1:
            r.kind = FLOAT;
            r.point = 3.5f;
            return r;
        case 2:
            r.kind = CHAR; // Remember that for a character you can just use a int.
            r.number = 'a';
            return r;
    }
    r.kind = INT;
    r.number = 0;
    return 0;
}
Here is a working example by analogy with the example in the message above.

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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include "stdafx.h"
#include <iostream>

struct Result
{
   enum { INT, FLOAT, CHAR } kind;
   union
   {
      int number;
      float point;
      char letter;
   };
};

Result GetRandomValue()
{
	Result r;
	int Val;

	Val = std::rand() % 3;

	switch ( Val )
	{
		case Result::INT:
			r.kind = Result::INT;
			r.number = 2;
			break;
		case Result::FLOAT:
			r.kind = Result::FLOAT;
			r.point = 3.5f;
			break;
		case Result::CHAR:
			r.kind = Result::CHAR;
			r.number = 'a';
			break;
	}

	return ( r );
};


int _tmain(int argc, _TCHAR* argv[])
{

	Result r = GetRandomValue();

	switch ( r.kind )
	{
		case Result::INT:
			std::cout << "It is an integer and equal to " << r.number;
			break;
		case Result::FLOAT:
			std::cout << "It is a float and equal to " << r.point;
			break;
		case Result::CHAR:
			std::cout << "It is a character and equal to " << r.letter;
			break;
	}

	std::cout << std::endl;
}
Last edited on
Topic archived. No new replies allowed.