python - switch case 的运行时类型检查

标签 python c++ dictionary types porting

我正在查看 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())选择使用哪个函数对值进行编码。

我有三个具体问题:

  1. template<typename T> struct type_name { ... }; 的目的是什么?在父类中name()功能?我什至不明白它是什么,模板有作用域吗?为什么不能 name()功能只是static_assert()如果调用编译错误?
  2. 为什么 template<> struct type_name<type> { static const char* name() {return "type";} }父类的值(value)观?简单地过载 name() 不是更清楚吗?不同类型的每个子类的函数?
  3. 如果我重载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_nameint成员函数 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/

相关文章:

python - ggplot2 中的克利夫兰点图

c++ - MFC:CSting IntelliSense:没有重载函数的实例

python - 当我们删除一个项目时,字典会调整大小吗?

C++ map 问题

集合的 python 操作

python - 如何解决CPU随机数生成器似乎失败,禁用硬件随机数生成错误

python - 对 Pandas 数据框中的行对应用函数

c++ - 单例线程安全程序

c++ - Qt - 如何从 QObject 转换为 UI 元素?

python - 求中位数的简单方法