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