我正在查看 bencode 规范,并且正在编写 deluge bit-torrent 客户端的 bencode 实现的 C++ 端口(用 python 编写)。 Python 实现包括一个 { data_types : callback_functions } 字典,函数包装器通过字典查找提供给包装器函数的变量的数据类型,轻松选择要使用的编码函数。 我在运行时搜索了与 python 原语等效的 C++ 变量类型,发现 typeid() 可能提供我正在寻找的内容。我知道我的代码不会存储 typeid() 函数返回值的结果,但我宁愿不依赖提供编译器特定字符串文字的函数。我找到了一个 solution这将允许我提供一种可移植的方法来手动将类型指定为字符串文字,我似乎很难全神贯注,模板对我来说是一场噩梦。
这是使用类型选择适当函数的 Python 代码:
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)
这是我发现的允许显式类类型枚举的 C++ 示例:
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.
}
如果这在我的类(class)中得到适当实现,我相信我可以使用 switch(variable.name())
选择使用哪个函数对值进行编码。
我有三个具体问题:
template<typename T> struct type_name { ... };
的目的是什么?在父类中name()
功能?我什至不明白它是什么,模板有作用域吗?为什么不能name()
功能只是static_assert()
如果调用编译错误?- 为什么
template<> struct type_name<type> { static const char* name() {return "type";} }
父类的值(value)观?简单地过载name()
不是更清楚吗?不同类型的每个子类的函数? - 如果我重载
name()
对于每个子类,并将子类变量转换为父类,我是否仍然调用name()
如果我调用variable.name()
,子类的函数调用?或者我会因为调用父类的name()
而导致编译时错误吗?功能?转换是否会改变类(class)的范围?
我认为我的问题源于对模板及其在 C++ 中的用途的误解,以及对继承缺乏理解。
最佳答案
模板入门
与动态 Python 相比,C++ 是一种静态类型语言。这意味着对象的类型在编译时是已知的(更多关于差异 here )。
在 C++ 中概括代码的一种方法是模板,它为 static or compile time polymorphism 提供了工具。 .要了解一个想法,请看一个 min
的 Python 示例。功能:
def min(a, b) :
if (a < b) :
return a
return b
要用 C++ 翻译这个,你会说
int min(int a, int b) {
return a < b ? a : b;
}
但问题是这种翻译是不准确的:它只适用于整数(以及任何可转换为整数的类型,这可能会导致截断)
克服这个问题的一种方法是为所有类型定义重载:
double min(double a, double b); // the definition would be the same as above
float min(float a, float b);
但这会很乏味且容易出错,而且远非通用。更好的解决方案是使用模板并将函数概括为任何类型 T
(支持 <
运算符):
template<typename T>
T min(T a, T b) { return a < b ? a : b; }
或者更好的是,您甚至可以处理两个参数具有不同类型的情况:
template<typename T1, typename T2>
auto min(T1 a, T2 b) -> decltype(a+b) { return a < b ? a : b; }
模板是一种强大的机制,我什至无法开始提供链接和来源;你必须通过谷歌搜索你的方式。
关于具体问题
语法
template<> struct<Atype> { ...
称为模板(完全)特化。它所做的是为特定模板参数强制类模板的布局。这里例如:template<> struct type_name<int> { static const char* name() {return "int";} };
我们被告知,当
T
的类型在type_name
是int
成员函数name()
返回“整数”这里没有子类,您没有构建层次结构。
name
是类模板中的成员函数,您正在为不同类型的模板参数专门化此类。
大局观
作为一种静态类型语言,C++ 可以为此提供更简洁的解决方案:
...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.
您可以根据您的类型直接参数化行为。
一个例子是重载你的函数
void Encode(int arg) { /* calls encode_int on arg */ }
void Encode(TupleType arg) { /* calls encode_list on arg */ }
其他示例是使用为每种类型的行为参数化的模板和策略。
关于python - switch case 的运行时类型检查,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24518868/