Run Time Type Identification

Hi:

It might be a misuse of RTTI as I've read a few articles on RTTI, and they seem to tackle different issues from mine.

Here's my problem:

Let's say we've built a template class LinkedList<T>, which has a few member functions typical to a linked list, e.g. append(T t), addAt(T t, int index), etc
Now I want to build a console based interactive testing tool to test the template class LinkedList<T>.

Ideally, if I type --- LinkedList<int> int_list
the tool should create a linked list containing integers.
Likewise, if I type --- LinkedList<string> str_list
the tool should create a linked list containing strings.

If I further type --- str_list.append("first")
the tool should recognize the command and append it to the str_list.


In order to achieve that, the first thing I do is parse the command by the user, namely --- str_list.append("first")

I need to extract three signatures from the command:
1, which object is operated on?
2, which member function is called?
3, a parameter list containing all parameters entered into the tool by the user


Obviously, an intuitive approach is I write very similar code pieces for different types as determined at run time.
1
2
3
4
5
6
7
8
9
10
11
//pseudocode
if(run time type is int)
{
   create and operate on LinkedList<int>;
}
else if(run time type is string)
{
   create and operate on LinkedList<string>;
}
else if ...
...



Essentially, I'm exhausting a finite number of (basic) types in C++ (No need to worry about complex objects).


Personally, I think this is really an ugly solution.
Ideally, I want one piece of "template" code for all types, not many similar duplicated code pieces for different types.
I put a double quote on template because template is a compile time concept, while what I really need is a run time "template".



Is that possible? How can I possibly do that?


P.S. I've thought about implementing and using my own heterogeneous container. I might want to push linked lists of different types(LinkedList<int>, LinkedList<string>, etc) altogether into the container. Then I might want to process them differently by type. Again, this doesn't escape the duplicate code paradigm.


Please enlighten me!
You could save everything as strings and remember the type associated with the container, then use a translation function when using any of the data. It does create a lot of overhead, having to translate each element that's used, but in terms of code duplication you only need a few basic translation functions.
@Gaminic:

Thank you very much for the quick response.
So you're suggesting it might not be possible to have run time "template" code, aren't you?

I think run time "template" is what I'm interested to investigate and hopefully implement.
Last edited on
Maybe 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
enum TypeName
{
    Integral,
    FloatingPoint,
    Character,
    Unknown
};

template <typename T>
struct Type
{
    static const TypeName Value = Unknown;
};

template <>
struct Type<int>
{
    static const TypeName Value = Integral;
};

template <>
struct Type<float>
{
    static const TypeName Value = FloatingPoint;
};

template <>
struct Type<char>
{
    static const TypeName Value = Character;
};

int main()
{
    if(Type<int>::Value == Integral)
        // ...

    return(0);
}

No?

Warning! Untested code.

Wazzak
@OsiumFramework:
Thanks a lot for the answer! But you're not even using T in
1
2
3
4
5
template <typename T>
struct Type
{
    static const TypeName Value = Unknown;
};



I kinda get what you mean. I think our ideas are fundamentally the same.
Maybe I didn't make myself clear enough. I'll try to show you where I get stuck in coding, and let's assume LinkedList<T> has been implemented somewhere. We're now implementing the Interactive Test system ---
1
2
3
4
5
6
7
// in main.cc
int main()
{
   InteractiveTest test;
   test.start();
   return 0;
};



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
// in InteractiveTest.cc
...
...
enum Operation {append, addAt, remove, ...}; //essentially the function names of a LinkedList<T>

struct CMD
{
   string obj_name; // signature 1: which object do we operate on?
   Operation op; // signature 2: which operation do we do on the object? Operation is enum
   list para_list;// signature 3: parameter list
   // here's where I get stuck --- I want a container that holds parameters of the user command string. However, when I write the code, I don't know yet what types of parameters will the user input. He may type in the terminal: append("first"); he may also type in the terminal: append(3.4); ... etc
   // My understanding is, if we simply store "first" or 3.4 as strings, we can write: list<string> para_list;
   // then in InteractiveTest::start(), we decide which if we go to depending on the type information we get from parsing "first" or 3.4
   // as I said, this solution isn't great and it is flawed in that we need to manually exhaust all basic data types.
   // I am looking for a container that can dynamically change types of variables it holds at run time, a.k.a "run time template" using my own silly definition
};


// simplified control flow
void InteractiveTest::start()
{
...
   string str;
   getline(cin, str); // user types in the terminal: append("first")
   CMD cmd = parseCmd(str); // step 1, parse the user command string and extract the 3 signatures
...
};




Please enlighten me! Either with more info on such a container, or with a work around solution!
Many thanks!
Topic archived. No new replies allowed.