C++ 在编译期间输出模板类名
我想知道是否有可能在编译时知道并输出模板类名。它看起来像这样:C++ 在编译期间输出模板类名,c++,templates,compile-time,C++,Templates,Compile Time,我想知道是否有可能在编译时知道并输出模板类名。它看起来像这样: template<typename T> class SomeTemplateClass { SOME_WAY_TO_PRINT_CLASS_NAME(T) }; template<typename T> class SomeTemplateClass { public: static int print() { int type_of
template<typename T>
class SomeTemplateClass
{
SOME_WAY_TO_PRINT_CLASS_NAME(T)
};
template<typename T>
class SomeTemplateClass
{
public:
static int print()
{
int type_of_T = 0;
return 0;
};
};
模板
类SomeTemplateClass
{
打印类名称(T)的一些方法
};
然后,每次调用模板类时,例如:
using C = SomeTemplateClass<std::string>;
使用C=SomeTemplateClass;
或
SomeTemplateClass实例;
编译器将回显如下消息:
note: Template argument of SomeTemplateClass is std::__cxx11::basic_string<char>
注意:SomeTemplateClass的模板参数是std::\uuuCXX11::basic\uString
就我搜索而言,我找到了一种方法,它使编译器崩溃,从而给出类的类型:
template<typename T>
class SomeTemplateClass
{
public:
using print = typename T::expected_crash;
};
using C = SomeTemplateClass<std::string>;
int main()
{
C::print err;
return 0;
}
模板
类SomeTemplateClass
{
公众:
使用print=typename T::预期的\u崩溃;
};
使用C=SomeTemplateClass;
int main()
{
C::打印错误;
返回0;
}
这就产生了:
error: no type named ‘expected_crash’ in ‘class std::__cxx11::basic_string<char>’
错误:“class std::\uuuucxx11::basic\u string”中没有名为“expected\u crash”的类型
但这与其说是一个干净的解决方案,不如说是一种黑客手段,我想知道是否还有其他解决方案
谢谢 您可以使用
typeid(T).name()
来确定类的名称。此模板有一个依赖的静态断言
,该断言将始终失败。编译器通常显示导致此类实例化失败的模板参数
template<class T>
struct NameOf {
static_assert(sizeof(T) != sizeof(T), "");
};
模板
结构名称{
静态断言(sizeof(T)!=sizeof(T),“”);
};
:在'struct NameOf'://的实例化中,还有另一种方法可以在编译时输出模板类名,但不会使编译器崩溃。可以使用警告,这里是未使用的变量警告
#define PRINT(T) template<typename T> \
int print_##T() \
{ \
int type_of_##T = 0; \
return 0; \
};\
int res_##T = print_##T<T>();
了解T的类型。此外,通过创建如下方法,可以在类内使用此解决方案:
template<typename T>
class SomeTemplateClass
{
SOME_WAY_TO_PRINT_CLASS_NAME(T)
};
template<typename T>
class SomeTemplateClass
{
public:
static int print()
{
int type_of_T = 0;
return 0;
};
};
模板
类SomeTemplateClass
{
公众:
静态整型打印()
{
int type_of_T=0;
返回0;
};
};
将在外部调用的方法:
int useless = SomeTemplateClass<T>::print();
int无用=SomeTemplateClass::print();
因此,它仍然是一种黑客行为,但至少编译器不再崩溃。“要确定类的名称”-严格来说,名称
只会为您提供一个唯一的、实现定义的标识符。没有任何东西可以保证它实际上是类名typeid(T).name()
在运行时起作用。我怀疑你能比你的黑客做得更好。您可以在适当的结构中移动static\u assert
,但仍然必须使代码失败,这可能不是您想要的。可能有一些编译器选项可以为您提供更详细的编译日志。看起来您需要类似于C++2a中的概念的内容。为了防止编译器崩溃,是否可以使用警告而不是错误来获取所需内容?我对概念一无所知。它们是如何工作的,以及它们在这里如何有用?您也可以使用其他警告,只需创建一个具有代表性或消息文本的荒谬标识符。@SergeyA如果启用了“警告是错误”,这将不会有帮助,您可能应该启用它。学究式地static\u断言(sizeof(t)!=sizeof(t),“”)代码>与静态断言(false,”)一样错误代码>(没有T
可以通过测试)<代码>静态断言(始终为假::值“”带有模板结构的代码>总是\u false:false\u类型{}
是有效的(我们可以创建伪类型并将always\u false
专门化为std::true\u type
)。但它是一个依赖表达式,这(在我的理解中)才是重要的。我认为标准不允许在实例化之前进行这种推断(但我很好奇被证明是错误的)。在实践中,依赖表达式就足够了,但标准指定了
template<typename T>
class SomeTemplateClass
{
public:
static int print()
{
int type_of_T = 0;
return 0;
};
};
int useless = SomeTemplateClass<T>::print();