需求

假设我有一种枚举类型:

enum fruit_type
{apple,banana,orange,
};

我时常会遇到需要将枚举值转换为字符串的情况,即我需要如下的函数:

const char* GetString_fruit(fruit_type fruit)

当我调用GetString_fruit(apple)时期望能得到字符串"apple"

然而它该怎么实现呢?
关键在于:原始的C++没有“反射系统”(或者说“类型系统”),枚举值在代码中的字符串,是无法知道的。

制作一个自己的C++反射系统是比较复杂的(虚幻4引擎有实现)。
而另一方面,“枚举值转换为字符串”这样的逻辑其实也可以用不太“优雅”的方式手动表示出来,例如:

const char* GetString_fruit(fruit_type fruit)
{if (fruit == fruit_type::apple)return "apple";else if (fruit == fruit_type::banana)return "banana";else if (fruit == fruit_type::orange)return "orange";elsereturn "";
}

但这样的缺点也很明显:

  • 字符串是手动打出的,有可能出错。
  • 虽然设计一些宏可以让代码少一些,但我想来想去,不管怎样都需要一个“时间复杂度”为N的劳动量,即枚举的值越多,劳动量越大。

因此,对于那些枚举的值较多的枚举类型,我想制作一个小工具来取代手工,自动生成这样一个函数的代码。

基本思路

我选择C#作为语言,理由如下:

  • C#具有反射机制
  • 在枚举方面,C#的语法和C++语法一样,这意味着我直接将C++中枚举的定义拷贝过来,不做任何处理,就是一个C#的枚举类型。

小工具的使用流程如下:

  1. 将C++的枚举定义拷贝到C#代码中。
  2. 运行C#程序,自动生成“将特定枚举值转换成字符串的C++函数”的代码
  3. 将生成的结果拷贝到C++中,即可使用。

小工具实现

创建一个控制台应用(.Net Framework)

C#代码如下(以“fruit_type”为例):

using System;
using System.Text;//要为其生成函数的枚举类型(拷贝自C++代码):
enum fruit_type
{apple,banana,orange,
};namespace AutoGenFuncForCppEnum
{class Program{static void Main(string[] args){//指定为其生成函数的枚举类型Type TheEnumType = typeof(fruit_type);//函数的代码string[] FunctionCode = GenerateFunctionCode(TheEnumType);//将函数的代码保存到文件中System.IO.File.WriteAllLines("GetEnumString_"+ TheEnumType.Name+".txt", FunctionCode, Encoding.UTF8);//将每一行都输出,查看结果foreach (string line in FunctionCode)Console.WriteLine(line);   Console.ReadLine();//没有特别的意义,只是想让程序等待一下}//为特定枚举类型生成函数代码static string[] GenerateFunctionCode(Type TheEnumType){//获得所有枚举值的字符串string[] EnumNames = Enum.GetNames(TheEnumType);//结果字符串数组(长度是枚举值数目+3,一个是函数头,一个是else return"";,一个是})string[] result = new string[EnumNames.Length + 3];//函数头:result[0] = "const char* GetEnumString_" + TheEnumType.Name + "(" + TheEnumType.Name + " value){";//添加每一个值的分支for (int i = 0; i < EnumNames.Length; i++){string enum_name = EnumNames[i];result[i + 1] = "    " + ((i > 0) ? "else " : "") + "if (value == " + TheEnumType.Name + "::" + enum_name + ")return \"" + enum_name + "\";";}//最后result[EnumNames.Length + 1] = "    else return \"\";";result[EnumNames.Length + 2] = "}";return result;}}
}

生成的结果是:

const char* GetEnumString_fruit_type(fruit_type value){if (value == fruit_type::apple)return "apple";else if (value == fruit_type::banana)return "banana";else if (value == fruit_type::orange)return "orange";else return "";
}

当为新的枚举类型生成代码时,需要做如下操作:

  1. 将开始的枚举类型(“fruit_type”)替换成新的枚举类型,例如enum_x
  2. 在Main中指定新的枚举类型,即Type TheEnumType = typeof(enum_x);

测试一个更复杂的枚举类型

using System;
using System.Text;//要为其生成函数的枚举类型(拷贝自C++代码):
enum VkResult
{VK_SUCCESS = 0,VK_NOT_READY = 1,VK_TIMEOUT = 2,VK_EVENT_SET = 3,VK_EVENT_RESET = 4,VK_INCOMPLETE = 5,VK_ERROR_OUT_OF_HOST_MEMORY = -1,VK_ERROR_OUT_OF_DEVICE_MEMORY = -2,VK_ERROR_INITIALIZATION_FAILED = -3,VK_ERROR_DEVICE_LOST = -4,VK_ERROR_MEMORY_MAP_FAILED = -5,VK_ERROR_LAYER_NOT_PRESENT = -6,VK_ERROR_EXTENSION_NOT_PRESENT = -7,VK_ERROR_FEATURE_NOT_PRESENT = -8,VK_ERROR_INCOMPATIBLE_DRIVER = -9,VK_ERROR_TOO_MANY_OBJECTS = -10,VK_ERROR_FORMAT_NOT_SUPPORTED = -11,VK_ERROR_FRAGMENTED_POOL = -12,VK_ERROR_UNKNOWN = -13,VK_ERROR_OUT_OF_POOL_MEMORY = -1000069000,VK_ERROR_INVALID_EXTERNAL_HANDLE = -1000072003,VK_ERROR_FRAGMENTATION = -1000161000,VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS = -1000257000,VK_ERROR_SURFACE_LOST_KHR = -1000000000,VK_ERROR_NATIVE_WINDOW_IN_USE_KHR = -1000000001,VK_SUBOPTIMAL_KHR = 1000001003,VK_ERROR_OUT_OF_DATE_KHR = -1000001004,VK_ERROR_INCOMPATIBLE_DISPLAY_KHR = -1000003001,VK_ERROR_VALIDATION_FAILED_EXT = -1000011001,VK_ERROR_INVALID_SHADER_NV = -1000012000,VK_ERROR_INCOMPATIBLE_VERSION_KHR = -1000150000,VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT = -1000158000,VK_ERROR_NOT_PERMITTED_EXT = -1000174001,VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT = -1000255000,VK_THREAD_IDLE_KHR = 1000268000,VK_THREAD_DONE_KHR = 1000268001,VK_OPERATION_DEFERRED_KHR = 1000268002,VK_OPERATION_NOT_DEFERRED_KHR = 1000268003,VK_PIPELINE_COMPILE_REQUIRED_EXT = 1000297000,VK_ERROR_OUT_OF_POOL_MEMORY_KHR = VK_ERROR_OUT_OF_POOL_MEMORY,VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR = VK_ERROR_INVALID_EXTERNAL_HANDLE,VK_ERROR_FRAGMENTATION_EXT = VK_ERROR_FRAGMENTATION,VK_ERROR_INVALID_DEVICE_ADDRESS_EXT = VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS,VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS_KHR = VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS,VK_ERROR_PIPELINE_COMPILE_REQUIRED_EXT = VK_PIPELINE_COMPILE_REQUIRED_EXT,VK_RESULT_MAX_ENUM = 0x7FFFFFFF
}namespace AutoGenFuncForCppEnum
{class Program{static void Main(string[] args){//指定为其生成函数的枚举类型Type TheEnumType = typeof(VkResult);//函数的代码string[] FunctionCode = GenerateFunctionCode(TheEnumType);//将函数的代码保存到文件中System.IO.File.WriteAllLines("GetEnumString_"+ TheEnumType.Name+".txt", FunctionCode, Encoding.UTF8);//将每一行都输出,查看结果foreach (string line in FunctionCode)Console.WriteLine(line);   Console.ReadLine();//没有特别的意义,只是想让程序等待一下}//为特定枚举类型生成函数代码static string[] GenerateFunctionCode(Type TheEnumType){//获得所有枚举值的字符串string[] EnumNames = Enum.GetNames(TheEnumType);//结果字符串数组(长度是枚举值数目+3,一个是函数头,一个是else return"";,一个是})string[] result = new string[EnumNames.Length + 3];//函数头:result[0] = "const char* GetEnumString_" + TheEnumType.Name + "(" + TheEnumType.Name + " value){";//添加每一个值的分支for (int i = 0; i < EnumNames.Length; i++){string enum_name = EnumNames[i];result[i + 1] = "    " + ((i > 0) ? "else " : "") + "if (value == " + TheEnumType.Name + "::" + enum_name + ")return \"" + enum_name + "\";";}//最后result[EnumNames.Length + 1] = "    else return \"\";";result[EnumNames.Length + 2] = "}";return result;}}
}

生成结果:

const char* GetEnumString_VkResult(VkResult value) {if (value == VkResult::VK_SUCCESS)return "VK_SUCCESS";else if (value == VkResult::VK_NOT_READY)return "VK_NOT_READY";else if (value == VkResult::VK_TIMEOUT)return "VK_TIMEOUT";else if (value == VkResult::VK_EVENT_SET)return "VK_EVENT_SET";else if (value == VkResult::VK_EVENT_RESET)return "VK_EVENT_RESET";else if (value == VkResult::VK_INCOMPLETE)return "VK_INCOMPLETE";else if (value == VkResult::VK_SUBOPTIMAL_KHR)return "VK_SUBOPTIMAL_KHR";else if (value == VkResult::VK_THREAD_IDLE_KHR)return "VK_THREAD_IDLE_KHR";else if (value == VkResult::VK_THREAD_DONE_KHR)return "VK_THREAD_DONE_KHR";else if (value == VkResult::VK_OPERATION_DEFERRED_KHR)return "VK_OPERATION_DEFERRED_KHR";else if (value == VkResult::VK_OPERATION_NOT_DEFERRED_KHR)return "VK_OPERATION_NOT_DEFERRED_KHR";else if (value == VkResult::VK_PIPELINE_COMPILE_REQUIRED_EXT)return "VK_PIPELINE_COMPILE_REQUIRED_EXT";else if (value == VkResult::VK_ERROR_PIPELINE_COMPILE_REQUIRED_EXT)return "VK_ERROR_PIPELINE_COMPILE_REQUIRED_EXT";else if (value == VkResult::VK_RESULT_MAX_ENUM)return "VK_RESULT_MAX_ENUM";else if (value == VkResult::VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS)return "VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS";else if (value == VkResult::VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS_KHR)return "VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS_KHR";else if (value == VkResult::VK_ERROR_INVALID_DEVICE_ADDRESS_EXT)return "VK_ERROR_INVALID_DEVICE_ADDRESS_EXT";else if (value == VkResult::VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT)return "VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT";else if (value == VkResult::VK_ERROR_NOT_PERMITTED_EXT)return "VK_ERROR_NOT_PERMITTED_EXT";else if (value == VkResult::VK_ERROR_FRAGMENTATION_EXT)return "VK_ERROR_FRAGMENTATION_EXT";else if (value == VkResult::VK_ERROR_FRAGMENTATION)return "VK_ERROR_FRAGMENTATION";else if (value == VkResult::VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT)return "VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT";else if (value == VkResult::VK_ERROR_INCOMPATIBLE_VERSION_KHR)return "VK_ERROR_INCOMPATIBLE_VERSION_KHR";else if (value == VkResult::VK_ERROR_INVALID_EXTERNAL_HANDLE)return "VK_ERROR_INVALID_EXTERNAL_HANDLE";else if (value == VkResult::VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR)return "VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR";else if (value == VkResult::VK_ERROR_OUT_OF_POOL_MEMORY)return "VK_ERROR_OUT_OF_POOL_MEMORY";else if (value == VkResult::VK_ERROR_OUT_OF_POOL_MEMORY_KHR)return "VK_ERROR_OUT_OF_POOL_MEMORY_KHR";else if (value == VkResult::VK_ERROR_INVALID_SHADER_NV)return "VK_ERROR_INVALID_SHADER_NV";else if (value == VkResult::VK_ERROR_VALIDATION_FAILED_EXT)return "VK_ERROR_VALIDATION_FAILED_EXT";else if (value == VkResult::VK_ERROR_INCOMPATIBLE_DISPLAY_KHR)return "VK_ERROR_INCOMPATIBLE_DISPLAY_KHR";else if (value == VkResult::VK_ERROR_OUT_OF_DATE_KHR)return "VK_ERROR_OUT_OF_DATE_KHR";else if (value == VkResult::VK_ERROR_NATIVE_WINDOW_IN_USE_KHR)return "VK_ERROR_NATIVE_WINDOW_IN_USE_KHR";else if (value == VkResult::VK_ERROR_SURFACE_LOST_KHR)return "VK_ERROR_SURFACE_LOST_KHR";else if (value == VkResult::VK_ERROR_UNKNOWN)return "VK_ERROR_UNKNOWN";else if (value == VkResult::VK_ERROR_FRAGMENTED_POOL)return "VK_ERROR_FRAGMENTED_POOL";else if (value == VkResult::VK_ERROR_FORMAT_NOT_SUPPORTED)return "VK_ERROR_FORMAT_NOT_SUPPORTED";else if (value == VkResult::VK_ERROR_TOO_MANY_OBJECTS)return "VK_ERROR_TOO_MANY_OBJECTS";else if (value == VkResult::VK_ERROR_INCOMPATIBLE_DRIVER)return "VK_ERROR_INCOMPATIBLE_DRIVER";else if (value == VkResult::VK_ERROR_FEATURE_NOT_PRESENT)return "VK_ERROR_FEATURE_NOT_PRESENT";else if (value == VkResult::VK_ERROR_EXTENSION_NOT_PRESENT)return "VK_ERROR_EXTENSION_NOT_PRESENT";else if (value == VkResult::VK_ERROR_LAYER_NOT_PRESENT)return "VK_ERROR_LAYER_NOT_PRESENT";else if (value == VkResult::VK_ERROR_MEMORY_MAP_FAILED)return "VK_ERROR_MEMORY_MAP_FAILED";else if (value == VkResult::VK_ERROR_DEVICE_LOST)return "VK_ERROR_DEVICE_LOST";else if (value == VkResult::VK_ERROR_INITIALIZATION_FAILED)return "VK_ERROR_INITIALIZATION_FAILED";else if (value == VkResult::VK_ERROR_OUT_OF_DEVICE_MEMORY)return "VK_ERROR_OUT_OF_DEVICE_MEMORY";else if (value == VkResult::VK_ERROR_OUT_OF_HOST_MEMORY)return "VK_ERROR_OUT_OF_HOST_MEMORY";else return "";
}

制作一个小工具:自动生成“将特定枚举值转换成字符串的C++函数”的代码相关推荐

  1. php 生成拼音缩写,将汉字转换成拼音的php函数

    将汉字转换拼音的php函数,有需要的朋友可以参考下. 复制代码 代码如下: /*--- *功能:将汉字转换为拼音 *函数:Pinyin */ function Pinyin($_String, $_C ...

  2. 怎样自己制作一个小程序?新手必知流程!

    随着市场需求的变化.不断成长的微信平台.随着周边小程序等功能的发布,商店公司开发小程序已经成为一种趋势.但是对于怎样自己制作一个小程序,很多卖家公司还是"新手",不明白应该使用什么 ...

  3. html自动生成价格,Excel技巧:用VLOOKUP函数制作产品报价单,自动生成价格!

    今天,教大家给大家分享一个用VLOOKUP函数制作产品报价单,自动生成价格的小技巧,输入对应的产品编号,就能够自动生成价格和日期,录入数量后能生成金额. 1.准备工作 Sheet1中是报价单表格,大家 ...

  4. 【python小项目】用python写一个小工具——番茄钟

    用python写一个小工具--番茄钟 最近听到朋友说在用番茄钟,有点兴趣也想下载一个来用用,后面仔细一想这玩意做起来也不难,索性自己顺手写一个算了,在这里也分享给大家了 一.功能简述 番茄钟即番茄工作 ...

  5. python小工具自动审单录凭证_那个天天在朋友圈晒加班的人,后来怎么样啦?

    一大学同学,印象中一直是个积极乐观.工作上进的人,几乎从没见过她有负能量的样子.最近却经常看到她凌晨在朋友圈发加班照片,配的文字语气中都是满满的负能量. 好像怎么努力都只能这样了 一个人.一条路走到黑 ...

  6. 【开源一个小工具】一键将网页内容推送到Kindle

    http://www.zijinxing.com/201412/124636.html 最近工作上稍微闲点,这一周利用下班时间写了一个小工具,其实功能挺简单但也小折腾了会. 工具名称:Simple S ...

  7. 分享一个小工具:Excel表高速转换成JSON字符串

    在游戏项目中一般都须要由策划制作大量的游戏内容,当中非常大一部分是使用Excel表来制作的.于是程序就须要把Excel文件转换成程序方便读取的格式. 之前项目使用的Excel表导入工具都是通过Offi ...

  8. python小工具自动审单录凭证_跟着老板工作了二十年,最近来了个新员工然后我被开除了...

    --二十年职场公司元老的吐槽 由来只有新人笑,有谁听见旧人哭 我是一个人事,公司初创的时候,我就加入了公司,一路上见证了公司从最初的几个人,到了现在百多号人的大团队.一路上工作勤勤恳恳虽无很大的功劳, ...

  9. aspose 转pdf表格大小乱了_自己写了一个小工具类:pdf转word,没有页数和大小限制,保真!...

    昨天下午遇到一个问题,想把一个比较大的pdf转化为word,结果使用了各种工具都收费.想着干脆写一个小工具吧,一开始使用的python等等试了好几个网上的代码,结果全都失真.于是乎不得不花了一下午自己 ...

最新文章

  1. window下使用nw.js开发桌面应用程序环境的搭建
  2. 使用pecl安装qqwry
  3. linux 如何以树形结构显示文件目录结构
  4. React技术栈——webpack
  5. 大工19春《计算机原理》在线作业2,大工19春《计算机原理》在线作业2.pdf
  6. linux建立与删除目录
  7. (转)光照图的理论和实践
  8. 计算机考研压分的学校,篡改分数,恶意压分...考研院校的骚操作大盘点!小心避坑!...
  9. android app功能测试,androidAPP功能测试要点幻灯片.pptx
  10. Github html文件在线预览方法
  11. python bytes是什么类型_python的Bytes类型
  12. Go第八篇之包的使用
  13. html点击按钮弹出悬浮窗_html弹窗,html网页弹窗代码
  14. GAN系列学习(1)——前生今世
  15. 红孩儿编辑器的模块设计12
  16. 3. 站在使用层面,Bean Validation这些标准接口你需要烂熟于胸
  17. 全站翻译分享---Localize平台的使用方式整理--Star.hou
  18. win10系统如何添加和切换多个桌面?
  19. Omdia 表示,智能手机出货量下降 12.9%
  20. 大搜车面试java_大搜车面试经验

热门文章

  1. 机器视觉运动控制一体机应用例程|包装盒检测解决方案
  2. 前端工程化:从切图仔到前端 Leader,如何跨越式成长
  3. Linux挂载磁盘,格式化,添加
  4. Ubuntu16.04升级内核并卸载不常用软件
  5. 利用Qt实现贪吃蛇小游戏
  6. 响应式web mqtt应用
  7. 将Pdf文件转换为Word
  8. Android平台标日单词查询背诵软件:日语学习机(包含标日初级48课和中级32课所有单词) 手机软件 移动软件
  9. 有趣的python代码系列五:可爱的小黄人
  10. 【产品经理交互常用软件】axure软件详细教程与学习指南