C++ 获取模板中的类型名称 [英] C++ Get name of type in template

查看:136
本文介绍了C++ 获取模板中的类型名称的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm writing some template classes for parseing some text data files, and as such it is likly the great majority of parse errors will be due to errors in the data file, which are for the most part not written by programmers, and so need a nice message about why the app failed to load e.g. something like:

解析 example.txt 时出错.[MySectiom]Key 的值 ("notaninteger") 不是有效整数

Error parsing example.txt. Value ("notaninteger")of [MySectiom]Key is not a valid int

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

I can work out the file, section and key names from the arguments passed to the template function and member vars in the class, however I'm not sure how to get the name of the type the template function is trying to convert to.

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

My current code looks like, with specialisations for just plain strings and such:

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));
    }
}

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

Id rather not have to make specific overloads for every type that the data files might use, since there are loads of them...

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

Also I need a solution that does not incur any runtime overhead unless an exception occurs, i.e. a completely compile time solution is what I want since this code is called tons of times and load times are already getting somewhat long.

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

Ok this is the solution I came up with:

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

I have a types.h containg the following

#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 文件中).

Then I can use the DEFINE_TYPE_NAME macro to in cpp files for each type I need to deal with (eg in the cpp file that defined the type to start with).

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

The linker is then able to find the appropirate template specialisation as long as it was defined somewhere, or throw a linker error otherwise so that I can add the type.

推荐答案

Jesse Beder 的解决方案可能是最好的,但是如果你不喜欢 typeid 给你的名字(我认为 gcc 给你的名字是混乱的),你可以执行以下操作:

Jesse Beder's solution is likely the best, but if you don't like the names typeid gives you (I think gcc gives you mangled names for instance), you can do something like:

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() 的函数,然后只针对以下情况这是不可接受的.

You could also combine the two, change name to be a function that by default calls typeid(T).name() and then only specialize for those cases where that's not acceptable.

这篇关于C++ 获取模板中的类型名称的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆