Run Time Type Identification

Jan 30, 2012 at 10:08am
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!
Jan 30, 2012 at 10:12am
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.
Jan 30, 2012 at 10:28am
@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 Jan 30, 2012 at 10:28am
Jan 30, 2012 at 3:43pm
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
Jan 30, 2012 at 6:26pm
@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.