Template Casting

Pages: 12
Goodmorning to everyone,

I'm facing a problem with templates, i need to compare a template with a type variable as follow in my code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14

enum class allowed_type { INT = 'i', FLOAT = 'f', CHAR = 'c' };

switch(type_of_template) {
case INT:
   int i = T;
   break;
case FLOAT:
   float f = T;
   break; 
case CHAR:
   char c = T;
   break;
}


Type_of_template is enum variable that contains one of the char in the enum declaration on the top of the code.

so, my problem is that when i try to assign T (= template variable) into the type variabile i'm 100% sure that the template is that type, so i couldn't encour in errors.
But the compiler stops me because he doesn't know the template type. i'm asking if there a tipe of cast that could help me solve this problem, forcing that template to assume a type in a right place.
I thought that the reinterpret_cast would help me but it doesn't.

Have you any suggestion?
We need more context. What exactly are you trying to do?

You might be looking for template specialization:

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
#include <iostream>

template<typename T>
void func(T x);

template<>
void func<int>(int x) {
    std::cout << "INT: " << x << '\n';
}

template<>
void func<double>(double x) {
    std::cout << "FLOAT: " << x << '\n';
}

template<>
void func<char>(char x) {
    std::cout << "CHAR: " << x << '\n';
}
 
int main() {
    func(1);
    func(1.23);
    func('x');
}

Last edited on
Have you any suggestion?

It's not really clear what you're trying to do. Here's code that has a function that returns a different character depending on what kind of object you pass to it. Does that do what you want?

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
#include <type_traits>

template <class T>
char whatType(T input)
{
    if constexpr (std::is_same<T, int>::value) return 'i';
    if constexpr (std::is_same<T, float>::value) return 'f';
    if constexpr (std::is_same<T, char>::value) return 'c';

    return 'u'; // unknown
}

#include <iostream>
using namespace std;

int main() {
	char x;
	cout << whatType(x) << '\n';
	
	int y;
	cout << whatType(y) << '\n';
	
	float z;
	cout << whatType(z) << '\n';
	
	short a;
	cout << whatType(a) << '\n';
	return 0;
}
I've got a different problem, i'll try to explain it better.
The code that @Repeater sent is what i implemented into "type_of_template"

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

enum class allowed_type { INT = 'i', FLOAT = 'f', CHAR = 'c' };

template<typename T> my_class {
public:
         my_class();
         allowed_type TemplateType() cost;
         void Assign();
private:
         int i;
         float f;
         char c;
         T temp;
};

template<typename T>
my_class<T>::my_class() {
        i = 0;
        f = 1.5;
        c = 'e';
}

template<typename T>
allowed_type my_class<T>::TemplateType() const {
	if (typeid(T) == typeid(int)) {
		return allowed_type::INT;
	}
	else if (typeid(T) == typeid(float)) {
		return allowed_type::FLOAT;
	}
	else if (typeid(T) == typeid(char)) {
		return allowed_type::CHAR;
	}
}

template<typename T>
void my_class<T>::Assign() {
  switch(TemplateType()) { 
  case INT:
     cout << i == temp;
     break;
  case FLOAT:
     cout << f == temp;
     break; 
  case CHAR:
     cout << c == temp;
     break;
  }
}

int main () {
     my_class<int> test;
     test.temp = 1;
     test.Assign();
     return 0;
}


Here it is my complete code, i need to do that comparison that you can see in Assign(), but compiler gives me the error said before.
Last edited on

You might be looking for template specialization:
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
#include <iostream>

template<typename T>
void func(T x);

template<>
void func<int>(int x) {
    std::cout << "INT: " << x << '\n';
}

template<>
void func<double>(double x) {
    std::cout << "FLOAT: " << x << '\n';
}

template<>
void func<char>(char x) {
    std::cout << "CHAR: " << x << '\n';
}
 
int main() {
    func(1);
    func(1.23);
    func('x');
}



so this is an overload of func, isn't it? but this means that i need to rewrite the function for all the types, is that true?
Last edited on
Here is your code with all the missing headers added, the namespaces added, the spelling mistakes fixed, the missing syntax added etc.

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
#include <typeinfo>
#include <iostream>

enum class allowed_type { INT = 'i', FLOAT = 'f', CHAR = 'c' };

template<typename T>
class my_class {
public:
         my_class();
         allowed_type TemplateType() const;
         void Assign();
         T temp;
private:
         int i;
         float f;
         char c;
        
};

template<typename T>
my_class<T>::my_class() {
        i = 0;
        f = 1.5;
        c = 'e';
}

template<typename T>
allowed_type my_class<T>::TemplateType() const {
	if (typeid(T) == typeid(int)) {
		return allowed_type::INT;
	}
	else if (typeid(T) == typeid(float)) {
		return allowed_type::FLOAT;
	}
	else if (typeid(T) == typeid(char)) {
		return allowed_type::CHAR;
	}
}

template<typename T>
void my_class<T>::Assign() {
  switch(TemplateType()) { 
  case allowed_type::INT:
    std::cout << (i == temp);
     break;
  case allowed_type::FLOAT:
    std::cout << (f == temp);
     break; 
  case allowed_type::CHAR:
    std::cout << (c == temp);
     break;
  }
}

int main () {
     my_class<int> test;
     test.temp = 1;
     test.Assign();
     return 0;
}


This code doesn't make much sense. Looks like you're make a kind of weird union type, of some kind of variant object
It is something similar to an union type, but my input need to be a template. I get your point, but i don't think that an union could help me in this case.

I know seems weird this code, but i need to get that bool in the cout for a function that i'm trying to create, in another project, so this is just something that helps me to learn.
Last edited on
So this is an overload of func

Avoid specializing function templates:
- https://wg21.link/p0551
- http://www.gotw.ca/publications/mill17.htm
- https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rt-specialize-function

Function template specializations aren't considered by overload resolution, and therefore interact with overloading in surprising ways.

Instead, just define overloads:
1
2
3
4
5
6
7
8
9
10
11
void func(int x) {
    std::cout << "INT: " << x << '\n';
}

void func(double x) {
    std::cout << "DOUBLE: " << x << '\n';
}

void func(char x) {
    std::cout << "CHAR: " << x << '\n';
}

Last edited on
but i don't think that an union could help me in this case.

They're generally a bad idea always.

1
2
3
4
5
6
7
8
9
10
11
void func(int x) {
    std::cout << "INT: " << x << '\n';
}

void func(double x) {
    std::cout << "DOUBLE: " << x << '\n';
}

void func(char x) {
    std::cout << "CHAR: " << x << '\n';
}


But how can i pass the template variable into func()?
Last edited on
so this is an overload of func, isn't it?

Yeah, I guess it is just function overloading, so just:

1
2
3
4
5
6
7
8
9
10
11
void func(int x) {
    std::cout << "INT: " << x << '\n';
}

void func(double x) {
    std::cout << "FLOAT: " << x << '\n';
}

void func(char x) {
    std::cout << "CHAR: " << x << '\n';
}

For what you've shown so far, that might be the best solution.

But how can i pass the template variable into func()?

Why do you need the template variable? You already know the type.
Maybe your class doesn't need to be a template at all.
Last edited on
What's the actual problem you're trying to solve, OP? Are you trying to store multiple types of data into the same variable?
@helios,
if I remember correctly from previous posts it's a about a workaround for not being able to use std::any.
Sorry to everyone if i've been absent for so long.


if I remember correctly from previous posts it's a about a workaround for not being able to use std::any.


@Thomas1965, You're right! that is always me ahah

What's the actual problem you're trying to solve, OP? Are you trying to store multiple types of data into the same variable?


@helios, It's really compicated to explain, because how correctly reminded by thomas1965 i'm working on a bigger project that allow me only to use c++11. In short, I need to store different types of objects that necessary comes from a template class, mainly identified by char, float and int.
In the class summed up in this topic, i need to assign to specific types variables the template content that comes from the object of the template class.

This short explanation include the answer to
Why do you need the template variable? You already know the type.
Maybe your class doesn't need to be a template at all.
made from @dutch.

Defenetly, @dutch, you're right this class write in this topic doesn't need to be a template class, but in trying to resume it i thought it was more clear using this example. Maybe it wasn't so i'm sorry for not being much clear, but i cannot copy there all my code for lot of reason that you could imagine.
I know i'm not allowing you to help me so much in this way, but i have not better choices.

Updating this topic i need to say too that i don't have find a solution yet.
If you only need to store char, float, and int (32-bit integers), then all you need is double. A double can store any of those values exactly.
No i need to convert others types of data from different objects too, but the assignment would be every time with obj_type1 = obj_type1. But if i learn how to do it with that primary types (int, char and float), then it will be easier to apply to my objects too
No i need to convert others types of data from different objects too
Such as...?
such as dates and hours, for example an object date has some function used to acquire and print dates, but only stores 3 int data (day, month, year).
This is the same for the hours that stores 3 int (hours, minutes, seconds) and has other functions likely dates.

Than there are other objects that stores different quantities of string variables
Last edited on
I'd use a polymorphic class. The other alternative is what Repeater suggested.

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
class Variant{
public:
    virtual ~Variant(){}
    virtual bool get(char &){
        return false;
    }
    virtual bool get(int &){
        return false;
    }
    virtual bool get(int &){
        return false;
    }
    virtual bool get(std::string &){
        return false;
    }
    //etc.
};

class Int : public Variant{
    int data;
public:
    //...
    bool get(int &dst) override{
        dst = this->data;
        return true;
    }
    //Optionally, if you want weak typing:
    bool get(std::string &dst) override{
        dst = std::to_string(this->data);
        return true;
    }
};

class String : public Variant{
    std::string data;
public:
    //...
    bool get(std::string &dst) override{
        dst = this->data;
        return true;
    }
};
No i can't use polymorphic class because i need just one object that manage all the types, and an union of all this different objects (that could maybe be a solution to contain all of them togheter) is not what i'm looking for.

What about the solution of @Repeater that you mentioned?
If you mean this, i'm already doing this in mine with typeid

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
#include <type_traits>

template <class T>
char whatType(T input)
{
    if constexpr (std::is_same<T, int>::value) return 'i';
    if constexpr (std::is_same<T, float>::value) return 'f';
    if constexpr (std::is_same<T, char>::value) return 'c';

    return 'u'; // unknown
}

#include <iostream>
using namespace std;

int main() {
	char x;
	cout << whatType(x) << '\n';
	
	int y;
	cout << whatType(y) << '\n';
	
	float z;
	cout << whatType(z) << '\n';
	
	short a;
	cout << whatType(a) << '\n';
	return 0;
}


As you can see in a part of a previous post
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <typeinfo>

template<typename T>
allowed_type my_class<T>::TemplateType() const {
	if (typeid(T) == typeid(int)) {
		return allowed_type::INT;
	}
	else if (typeid(T) == typeid(float)) {
		return allowed_type::FLOAT;
	}
	else if (typeid(T) == typeid(char)) {
		return allowed_type::CHAR;
	}
}
Last edited on
Pages: 12