I am looking at the bencode specification and I am writing a C++ port of the deluge bit-torrent client's bencode implementation (written in python). The Python implementation includes a dictionary of { data_types : callback_functions } by which a function wrapper easily selects which encoding function to use by a dictionary look-up of the data type of the variable provided to the wrapper function. I did a search for identifying variable types during run-time of C++ equivalents to python primitives, and found that typeid() might provide what I am looking for. I know that my code will not be storing the results of the typeid() function return value, but I would rather not rely on a function that provides compiler specific string literals. I found a solution that would allow me to provide a portable means to specify the type manually as a string literal, it seems difficult for me to wrap my head around, templates are a nightmare to me.
Here is the Python code in which types are used to select appropriate functions:
encode_func = {}
encode_func[Bencached] = encode_bencached
encode_func[IntType] = encode_int
encode_func[LongType] = encode_int
encode_func[StringType] = encode_string
encode_func[ListType] = encode_list
encode_func[TupleType] = encode_list
encode_func[DictType] = encode_dict
try:
from types import BooleanType
encode_func[BooleanType] = encode_bool
except ImportError:
pass
def bencode(x):
r = []
encode_func[type(x)](x, r)
return ''.join(r)
Here is the C++ sample I found that allows for explicit class type enumeration:
struct Foobar;
template<typename T> struct type_name
{
static const char* name() { static_assert(false, "You are missing a DECL_TYPE_NAME"); }
};
template<> struct type_name<int> { static const char* name() {return "int";} };
template<> struct type_name<string> { static const char* name() {return "string";} };
template<> struct type_name<Foobar> { static const char* name() {return "Foobar";} };
int main()
{
cout << type_name<int>::name(); // prints "int"
cout << type_name<float>::name(); // compile time error. float wasn't declared.
}
If this was implemented appropriately in my classes, I believe I could use switch(variable.name())
to select which function to use to encode the value.
I have three specific questions:
- What is the purpose of
template<typename T> struct type_name { ... };
in the parent classname()
function? I don't really even understand what it is, do templates have scopes? Why can't thename()
function juststatic_assert()
a compile error if called? - Why are the
template<> struct type_name<type> { static const char* name() {return "type";} }
values in the parent-class? Would it not be more clear to simply over-load thename()
function for each child-class of a different type? - If I over-load
name()
for each child-class, and cast a child-class variable to the parent-class, do I still call thename()
function call of the child-class if I callvariable.name()
? or will I cause a compile time error because I called the parent-class'sname()
function? Does casting change the scope of the class?
I believe that my question stems from a mis-understanding of templates and their purpose in C++, as well as a lack of understanding of inheritance.