C 获取模板中的类型名称

新手上路,请多包涵

我正在编写一些模板类来解析一些文本数据文件,因此很可能绝大多数解析错误是由于数据文件中的错误造成的,这些错误大部分不是由程序员编写的,所以需要关于为什么应用程序无法加载的好消息,例如:

解析 example.txt 时出错。 [MySectiom]Key 的值(“notaninteger”)不是有效的 int

我可以从传递给模板函数的参数和类中的成员变量中计算出文件、节和键名,但是我不确定如何获取模板函数试图转换为的类型的名称。

我当前的代码看起来像,专门针对纯字符串等:

 template<typename T> T GetValue(const std::wstring &section, const std::wstring &key)
{
    std::map<std::wstring, std::wstring>::iterator it = map[section].find(key);
    if(it == map[section].end())
        throw ItemDoesNotExist(file, section, key)
    else
    {
        try{return boost::lexical_cast<T>(it->second);}
        //needs to get the name from T somehow
        catch(...)throw ParseError(file, section, key, it->second, TypeName(T));
    }
}

我宁愿不必为数据文件可能使用的每种类型都进行特定的重载,因为它们有很多……

我还需要一个解决方案,除非发生异常,否则不会产生任何运行时开销,即我想要一个完全编译时的解决方案,因为这段代码被调用了很多次并且加载时间已经变得有些长了。

编辑:好的,这是我想出的解决方案:

我有一个 types.h 包含以下内容

#pragma once
template<typename T> const wchar_t *GetTypeName();

#define DEFINE_TYPE_NAME(type, name) \
    template<>const wchar_t *GetTypeName<type>(){return name;}

然后我可以在 cpp 文件中为我需要处理的每种类型使用 DEFINE_TYPE_NAME 宏(例如,在定义要开始的类型的 cpp 文件中)。

然后链接器能够找到适当的模板特化,只要它在某处定义,否则抛出链接器错误,以便我可以添加类型。

原文由 Fire Lancer 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.4k
2 个回答

Jesse Beder 的解决方案可能是最好的,但如果你不喜欢 typeid 给你的名字(例如我认为 gcc 给你的名字是乱码),你可以这样做:

 template<typename T>
struct TypeParseTraits;

#define REGISTER_PARSE_TYPE(X) template <> struct TypeParseTraits<X> \
    { static const char* name; } ; const char* TypeParseTraits<X>::name = #X

REGISTER_PARSE_TYPE(int);
REGISTER_PARSE_TYPE(double);
REGISTER_PARSE_TYPE(FooClass);
// etc...

然后像这样使用它

throw ParseError(TypeParseTraits<T>::name);

编辑:

您也可以将两者结合起来,将 name 更改为默认调用 typeid(T).name() 的函数,然后仅专门针对那些不可接受的情况。

原文由 Logan Capaldo 发布,翻译遵循 CC BY-SA 3.0 许可协议

从 c++20 开始,我们可以使用 std::source_location::function_name() 来获取包含函数名称和参数的字符串。

 template<typename T>
consteval auto type_name()
{
    std::string_view func_name(std::source_location::current().function_name()); // returns something like: consteval auto type_name() [with T = int]

    auto extracted_params = ... Do some post processing here to extract the parameter names.
    return extracted_params;
}

注意:在撰写本文时(2022 年 10 月)MSVC 不报告模板参数,因此该解决方案在那里不起作用。遗憾的是, function_name() 的返回值形式在标准中并没有明确规定,但我们至少希望他们在以后的版本中加入模板参数。

例子

原文由 florestan 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题