1 function to for multiple "gets" using template

let's suppose I have program like the one below, is it possible to make a single "get" function to retrieve any of the used variables in union using templates or something else?

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
#include <iostream>
#include <vector>
using namespace std;

enum VarType
{
	NONE, TYPE_INT, TYPE_LONG, TYPE_DOUBLE, TYPE_STRING
};

class myclass
{
public:
	myclass(int i) {set(i);}
	myclass(long l) {set(l);}
	myclass(double d) {set(d);}
	myclass(char *c) {set(c);}

	void set(int i) {this->i = i; type = TYPE_INT;}
	void set(long l) {this->l = l; type = TYPE_LONG;}
	void set(double d) {this->d = d; type = TYPE_DOUBLE;}
	void set(char *c) {this->c = c; type = TYPE_STRING;}
private:
	VarType type = NONE;
	union
	{
		int i;
		long l;
		double d;
		char *c;
	};
};

int main() {
	vector<myclass> classes;
	classes.push_back(myclass(10));
	classes.push_back(myclass((long)15));
	classes.push_back(myclass(1.5));
	classes.push_back(myclass("hello"));
	
	for(unsigned i = 0; i < classes.size(); i++)
	{
		//a single function to get the value from class, based on type variable (or without it)
		//something like this:
		cout << classes[i].get() << endl;
		//should return: 10, 15, 1.5, hello
	}
	
	return 0;
}
Last edited on
Hi,
Well, it is not that hard.
1
2
3
4
5
6
7
8
9
10
11
char get()
{
      switch(type)
      {
            case TYPE_INT : cout << i; break;
            case TYPE_LONG : cout << l; break;
            case TYPE_DOUBLE : cout << d; break;
            case TYPE_STRING : cout << c; break;
      }
      return ' ';
}
Does that help you? :)
not really, I want to get the values and store them, not print them, that was just an example
Sorry, but there is noway a function can have multiple return value types. Template has nothing to do with it. But good news : All of your members can be converted into a universal int, if you wish. Only thing your double member will truncated before it can return as a return value.

That said, template is a very good idea. But you often need to at least give a compiler a hint (especially in your case) in order to be able to use them. Talking about without giving a compiler a hint. A compiler can only know the appropriate return value type for each situation during its compile time if a hint is specified. Then you are fine, but if you just call your get function the universal way (classes[i].get()) and expect your program to predict the appropriate return value type at run-time, well your member type may change during your program's run-time, being outside what a complier can offer to help. Compilers do nothing to help you with your program's run-time excepting for debugging. Your function cannot adapt to return a proper return value type during its execution when you need it the most, and well that's it.


However, there's still hope. Another way for you : make operator functions (because they can be overloaded)

Can you get an idea?
I actually made operator functions but still would somehow prefer to do it with templates, as I found several threads on stackoverflow saying that it's possible but (in that specific case) useless, or messy, or something like that (and I never used templates before, so this might actually teach me something, if possible)

well my get function would kinda know what to return, as there's the "type" variable that stores what my class holds...

so is something like this possible?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//within class
template<typename T>
T get();

template<typename T>
T myclass::get()
{
	if(type == TYPE_INT)
		//return int
	else if(type == TYPE_LONG)
		//return long
	else if(type == TYPE_DOUBLE)
		//return double
	else if(type == TYPE_STRING)
		//return c
}
Last edited on
This link can be a good reference :
http://stackoverflow.com/questions/14840173/c-same-function-parameters-with-different-return-type

Let me know if you cannot implement one yourself.
I want to get the values and store them, not print them

Store them where? You will need a type that can receive all of your alternatives, which means another variant.

C++17-so-far now includes std::variant ( http://en.cppreference.com/w/cpp/utility/variant ) , but until it comes to gcc near you, you can use boost:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <boost/variant.hpp>
#include <iostream>
#include <string>
#include <vector>
using myclass = boost::variant<int, long, double, std::string>;
int main() {
    std::vector<myclass> classes = {10, 15l, 1.5, "hello"};
    for(auto v: classes) {
        // to print, boost supports operator<< on variants
        std::cout << v << ' ';
        // to do anything more fancy, visit
        myclass w = apply_visitor([](auto arg) -> myclass {return arg + arg;}, v);
        std::cout << " doubled: " << w << '\n';
    }
}

live demo: http://coliru.stacked-crooked.com/a/ad4de9f728ceb72a
10  doubled: 20
15  doubled: 30
1.5  doubled: 3
hello  doubled: hellohello
Last edited on
@5a8Ym39o6

what is that get_value function? I seem to not be able to find it anywhere, is it custom made? what is it supposed to do? convert any of the values I'll be using to string? something like

1
2
3
4
5
string get_value(int i) {return to_string(i);}

string get_value(long l) {return to_string(l);}

string get_value(double d) {return to_string(d);}


or is it something else?

edit: nah, it takes string as argument and value (return of get_value) is string as well.. what's going on with that function?
Last edited on
@Cubbi

store them in the variable of specific type (int, long, double, char...) as mentioned above, the thread 5a8Ym39o6 posted looks fine so far so I'll try to implement that
Topic archived. No new replies allowed.