Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/127.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 可以将模板参数用作字符串吗?_C++_Templates - Fatal编程技术网

C++ 可以将模板参数用作字符串吗?

C++ 可以将模板参数用作字符串吗?,c++,templates,C++,Templates,我想使用传递的模板参数作为字符串。可能吗 T是类,我需要更改什么才能使代码正常工作 void registerClass(const std::string &name, Handler *handler); template<class T> void registerClass() { registerClass( "get T as string", new DefaultHandler<T>()); } void注册表类(const std::s

我想使用传递的模板参数作为字符串。可能吗

T是类,我需要更改什么才能使代码正常工作

void registerClass(const std::string &name, Handler *handler);

template<class T>
void registerClass() {
   registerClass( "get T as string", new DefaultHandler<T>());
}
void注册表类(const std::string和name,Handler*Handler);
模板
无效注册表类(){
registerClass(“获取T作为字符串”,new DefaultHandler());
}
您可以使用
typeid(T)
获得描述类型的
std::type\u info
结构。此结构又有一个
name()
成员,该成员应为您提供名称

template<class T>
void fooClass() {
   foo( "get " + std::string( typeid(T).name() ) +" as string", new DefaultHandler<T>());
}
模板
void类(){
foo(“get”+std::string(typeid(T).name())+“as string”,new DefaultHandler());
}
您可以使用
typeid(T)
获得描述类型的
std::type\u info
结构。此结构又有一个
name()
成员,该成员应为您提供名称

template<class T>
void fooClass() {
   foo( "get " + std::string( typeid(T).name() ) +" as string", new DefaultHandler<T>());
}
模板
void类(){
foo(“get”+std::string(typeid(T).name())+“as string”,new DefaultHandler());
}

最接近字符串形式的类型是
typeid(T)->name()
。但是,类型名没有标准化,因此您不能信任从中获取有效的名称。符合标准的实现很可能会为所有类型名返回空字符串。

最接近字符串类型的方法是使用
typeid(T)->name()。但是,类型名没有标准化,因此您不能信任从中获取有效的名称。符合标准的实现很可能会为所有类型名返回空字符串。

C++不像C#或Java那样有空字符串。这不是一个错误。反思已经被考虑了不止一次,并且被有意地排除在语言之外

然而,你可以得到与你的设计相近的东西。你将不得不自己做很多工作。本质上,您必须用一种故意不提供反射的语言来实现反射

您当前的设计非常接近。如果我按照您的方式实施反射,我会:

class Reflection_registry {
    std::map<std::string, Handler*> registry_;

public:
    void registerClass(const std::string& name, Handler* handler) {
        registry_[name] = handler;
    }

    Handler* getHandlerForClass(std::string& name) {
        std::map<std::string, Handler*>::iterator itor = registry_.find(name);
        return itor == registry_.end() ? NULL : itor->second;
    }
}
类反射\u注册表{
地图注册;
公众:
无效注册表类(const std::string&name,Handler*Handler){
注册表\[name]=处理程序;
}
Handler*getHandlerForClass(标准::字符串和名称){
std::map::迭代器itor=registry\uux.find(名称);
return-itor==registry.end()?NULL:itor->second;
}
}
问题是,您将负责手工提供相关的名称,并使其保持最新。正如其他人所建议的那样,您可以使用
typeid
和s来生成名称——这与
std::type_info
的设计目的差不多。

C++不像C++或Java那样。这不是一个错误。反思已经被考虑了不止一次,并且被有意地排除在语言之外

然而,你可以得到与你的设计相近的东西。你将不得不自己做很多工作。本质上,您必须用一种故意不提供反射的语言来实现反射

您当前的设计非常接近。如果我按照您的方式实施反射,我会:

class Reflection_registry {
    std::map<std::string, Handler*> registry_;

public:
    void registerClass(const std::string& name, Handler* handler) {
        registry_[name] = handler;
    }

    Handler* getHandlerForClass(std::string& name) {
        std::map<std::string, Handler*>::iterator itor = registry_.find(name);
        return itor == registry_.end() ? NULL : itor->second;
    }
}
类反射\u注册表{
地图注册;
公众:
无效注册表类(const std::string&name,Handler*Handler){
注册表\[name]=处理程序;
}
Handler*getHandlerForClass(标准::字符串和名称){
std::map::迭代器itor=registry\uux.find(名称);
return-itor==registry.end()?NULL:itor->second;
}
}

问题是,您将负责手工提供相关的名称,并使其保持最新。正如其他人所建议的,您可以使用
typeid
和s来生成名称——这与
std::type_info
的设计目的差不多。

它必须是模板参数吗?也许C处理器可以帮助:

void registerClass(const std::string &name, Handler *handler);

#define REGISTER_CLASS(t) (registerClass( #t, new DefaultHandler<t>()))

void RegisterMyClasses() {  
  REGISTER_CLASS(int);
  REGISTER_CLASS(Foo);
}
void注册表类(const std::string和name,Handler*Handler);
#定义寄存器类(t)(寄存器类(#t,新的DefaultHandler())
void registerMyClass(){
注册类别(int);
注册课程(Foo);
}

它必须是模板参数吗?也许C处理器可以帮助:

void registerClass(const std::string &name, Handler *handler);

#define REGISTER_CLASS(t) (registerClass( #t, new DefaultHandler<t>()))

void RegisterMyClasses() {  
  REGISTER_CLASS(int);
  REGISTER_CLASS(Foo);
}
void注册表类(const std::string和name,Handler*Handler);
#定义寄存器类(t)(寄存器类(#t,新的DefaultHandler())
void registerMyClass(){
注册类别(int);
注册课程(Foo);
}

<代码>代码>登记器< /Cord>是C++关键字,不能用它作为标识符。我已经编辑了它,它不是真正的代码:)您真的需要将类型作为字符串,还是每个类型使用不同的字符串作为某种字典键?我需要它作为字符串。因为我将使用该类名访问它。请看。阅读答案,这是一个很好的模式。如果你想让名字被混淆,使用<代码> ABI::YXCXAYDEMAGLYLE()/Cux>(GCC)<代码>登记器< /Cord>是C++关键字,不能用它作为标识符。我已经编辑了它,它不是真正的代码:)您真的需要将类型作为字符串,还是每个类型使用不同的字符串作为某种字典键?我需要它作为字符串。因为我将使用该类名访问它。请看。阅读答案,这是一个很好的模式。如果需要demangle,则名称使用
abi::\uucxa\uDemangle()
(gcc)
typeid
是一个运算符,而不是一个函数,因此它不存在于
std:
命名空间中。它返回一个指针,因此您需要使用
->
而不是
。是的,没有标准化,它生成带有数字的名称。所以,如果可能的话,我正在寻找其他方法,而不在我使用的每个类中声明静态方法。@MiroK:如果你真的需要类名,那你就走运了