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

查看:678
本文介绍了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]键的值("notaninteger")不是有效的整数

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

我可以从传递给模板函数的参数以及类中的成员vars得出文件,段和键名,但是我不确定如何获取模板函数尝试转换的类型的名称

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不必为数据文件可能使用的每种类型进行特定的重载,因为它们有很多负载...

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:

我有一个类型.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;}

然后,我可以使用DEFINE_TYPE_NAME宏在需要处理的每种类型的cpp文件中(例如,在定义开头类型的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天全站免登陆