#include <iostream>
#include <string>
using namespace std;
template <class T>
const char* my_type_id()
{
return "Unknown";
}
#define REGISTER_TYPE(some_type) \
template <> inline \
const char* my_type_id<some_type>() \
{ \
return #some_type; \
}
REGISTER_TYPE(int)
REGISTER_TYPE(std::string)
int main()
{
// displays "int"
cout << my_type_id<int>() << endl;
// displays "std::string"
cout << my_type_id<string>() << endl;
// displays "Unknown" - we haven't registered char
cout << my_type_id<char>() << endl;
}
这种方法最好的地方在于,您不必担心跨翻译单元或模块的问题。唯一需要注意的是名称冲突,在这种情况下,您可以指定一个命名空间来帮助避免它们(例如使用"std::string"而不是简单的"string")。
我们将此解决方案用作boost::any的替代方案,我们通过SDK提供boost::any(因此无法使用boost,因为这将要求我们的用户安装boost,或者我们要发送boost的部分内容,这可能会导致安装了不同版本的boost的用户之间发生冲突)。它不像boost::any那样自动化,因为它需要手动注册支持的类型(在这方面更接近于boost::variant),但不需要我们的SDK用户启用RTTI,并且可以在模块边界上可移植使用(我不确定是否可以依赖RTTI在不同编译器、设置和模块之间产生相同的信息-我怀疑)。
现在,您可以根据需要使用这些与类型相关联的字符串ID。一个例子是将创建函数映射到这些字符串ID,以便您可以通过factory::create("std::string")创建std::string的实例。请注意,这只是演示目的的假设情况,因为使用工厂来创建std::string会相当奇怪。
@stinky472: 我使用了一个与你上面写的代码类似的代码...
我的问题是,我使用宏声明了一个项目的命名空间,因此,如果有类c在a :: b :: c中,就有了类的完整名称。
我所做的是改变我的代码,不再依赖于命名空间本身,而是在类宏定义时添加一个新的参数来告诉它使用的命名空间,如:
newclass(a::b, c): public d{
};
我的计数器问题在于命名空间被用于许多类中,从而在命名空间宏中创建相同的变量名,通过以上的新方法,我不再需要计数器...
感谢您的帮助,
Jonathan