å°ç人é½ç¥éC++éæä¸ä¸ªtypeidæä½ç¬¦å¯ä»¥ç¨æ¥è·åä¸ä¸ªç±»å/表达å¼çå称ï¼
std::cout << typeid(int).name() << std::endl;
ä½æ¯è¿ä¸ªname()çè¿åå¼æ¯
åå³äºç¼è¯å¨ç
ï¼å¨vcågccä¸æå°åºæ¥çç»æå¦ä¸ï¼
int // vc
i // gcc
ä¸ä¸ªç¨å¾®é¿ä¸ç¹çç±»åå称ï¼æ¯å¦ï¼
class Foo {};
std::cout << typeid(Foo*[10]).name() << std::endl;
æåºæ¥æ¯è¿ä¸ªææï¼
class Foo * [10] // vc
A10_P3Foo // gcc
ï¼è¯è¯´gccæ¨çè¿åç»æçæ¯ããï¼
å½ç¶äºï¼æ³å¨gccéå¾å°å微软差ä¸å¤æ¾ç¤ºææçæ¹æ³ä¹æ¯æçï¼é£å°±æ¯ä½¿ç¨
__cxa_demangle
ï¼
char* name = abi::__cxa_demangle(typeid(Foo*[10]).name(), nullptr, nullptr, nullptr);
std::cout << name << std::endl;
free(name);
æ¾ç¤ºææï¼
Foo* [10]
å
ä¸è¯´ä¸åç¼è¯å¨ä¸çéé
é®é¢ï¼æ¥ççä¸é¢è¿ä¸ªä¼æå°åºå¥ï¼
// vc
std::cout << typeid(const int&).name() << std::endl;
// gcc
char* name = abi::__cxa_demangle(typeid(const int&).name(), nullptr, nullptr, nullptr);
std::cout << name << std::endl;
free(name);
æ¾ç¤ºææï¼
int // vc
int // gcc
å¯ç±çcvéå®ç¬¦åå¼ç¨é½è¢«ä¸¢æäº=.=
å¦æç´æ¥å¨typeidçç»æä¸å ä¸è¢«ä¸¢å¼çä¿¡æ¯ï¼å¯¹äºä¸äºç±»åèè¨ï¼å¦å½æ°æéå¼ç¨ï¼å¾å°çå°ä¸æ¯ä¸ä¸ªæ£ç¡®çç±»åå称ã
æ³è¦è·å¾ä¸ä¸ªç±»åçå®æ´å称ï¼å¹¶ä¸è·å¾çå称å¿
é¡»è¦æ¯ä¸ä¸ªæ£ç¡®çç±»åå称ï¼åºè¯¥ææ ·åå¢ï¼
ä¸ãå¦ä½æ£æ¥C++ä¸çç±»å
æ们éè¦ä¸ä¸ªæ³åç±»ï¼ç¨ç¹å/åç¹åæºå¶éææ£æ¥åºC++ä¸çåç§ç±»åï¼å¹¶ä¸ä¸è½å¿½ç¥æç±»åéå®ç¬¦ï¼type-specifiersï¼ååç§å£°æ符ï¼declaratorsï¼ã
å
æ¥èèä¸ä¸ªæç®åç类模æ¿ï¼
template <typename T>
struct check
{
// ...
};
åå¦å¨å®çåºç¡ä¸ç¹åï¼éè¦åå¤å°ä¸ªçæ¬å¢ï¼æ们å¯ä»¥ç¨å¾®å®ç°ä¸è¯è¯ï¼
template <typename T> struct check<T &>;
template <typename T> struct check<T const &>;
template <typename T> struct check<T volatile &>;
template <typename T> struct check<T const volatile &>;
template <typename T> struct check<T &&>;
template <typename T> struct check<T const &&>;
template <typename T> struct check<T volatile &&>;
template <typename T> struct check<T const volatile &&>;
template <typename T> struct check<T *>;
template <typename T> struct check<T const *>;
template <typename T> struct check<T volatile *>;
template <typename T> struct check<T const volatile *>;
template <typename T> struct check<T * const>;
template <typename T> struct check<T * volatile>;
template <typename T> struct check<T * const volatile>;
template <typename T> struct check<T []>;
template <typename T> struct check<T const []>;
template <typename T> struct check<T volatile []>;
template <typename T> struct check<T const volatile []>;
template <typename T, size_t N> struct check<T [N]>;
template <typename T, size_t N> struct check<T const [N]>;
template <typename T, size_t N> struct check<T volatile [N]>;
template <typename T, size_t N> struct check<T const volatile [N]>;
// ......
è¿è¿è¿è¿æ²¡æå®ãæåå¦å¯è½ä¼è¯´äºï¼æ们ä¸æ¯æä¼å¤§çå®åï¼è¿äºä¸è¥¿é½åæ¯ä¸ä¸ªæ¨¡åå»åºæ¥çï¼å¼ä¸ä¸ªå®æ¹éçæä¸ä¸å°±å®äºã
å®é
ä¸å½æ们ççä¿¡å¿æ»¡æ»¡çå¨æå»åè¿äºå®çæ¶åï¼æåç°éé
ä¸çç»å¾®å·®å«ä¼è®©å®åå¾é常çè¦ï¼æ¯å¦&å*çå·®å«ï¼[]å[N]çå·®
å«ï¼è¿æå½æ°ç±»åãå½æ°æéãå½æ°æéå¼ç¨ãå½æ°æéæ°ç»ãç±»æåæéãâ¦â¦ï¼ãå½æ们ä¸ä¸ç½ååºéè¦ç¹åçç»èæ¶ï¼ä¸ç±å¾æå¹C++ç±»åç³»ç»çå¤æåçº
ç»ã
ä½æ¯ä¸é¢ççç±å¹¶ä¸æ¯è¿ä¸ªæè·¯çè´å½ä¼¤ã
ä¸å¯è¡çå°æ¹å¨äºï¼æ们å¯ä»¥åä¸ä¸ªå¤ç»´æéï¼æå¤ç»´æ°ç»ï¼ç±»åæ¯å¯ä»¥åµå¥çãæ»ä¸å¯è½ä¸ºæ¯ä¸ä¸ªç»´åº¦é½ç¹åä¸ä¸ªæ¨¡æ¿å§ã
ä¸è¿æ£ç±äºç±»åå
¶å®æ¯åµå¥çï¼æ们å¯ä»¥ç¨æ¨¡æ¿å
ç¼ç¨çåºæ¬æè·¯æ¥æå®è¿ä¸ªé®é¢ï¼
template <typename T> struct check<T const> : check<T>;
template <typename T> struct check<T volatile> : check<T>;
template <typename T> struct check<T const volatile> : check<T>;
template <typename T> struct check<T & > : check<T>;
template <typename T> struct check<T &&> : check<T>;
template <typename T> struct check<T * > : check<T>;
// ......
ä¸ä¸ªç®åç继æ¿ï¼å°±è®©ç¹ååå¾simpleå¾å¤ãå 为å½æ们èååºä¸ä¸ªç±»åï¼æ¯å¦T *ï¼ä¹åçTå
¶å®æ¯æºå¸¦ä¸äºé¤*ä¹å¤ææå
¶ä»ç±»åä¿¡æ¯çä¸ä¸ªç±»åãé£ä¹æè¿ä¸ªTåéå¤æå
¥checkä¸ï¼å°±ä¼ç»§ç»èåå®çä¸ä¸ä¸ªç±»åç¹å¾ã
å¯ä»¥å
ç¨æéãå¼ç¨çèåæ¥ççææï¼
#include <iostream>
template <typename T>
struct check
{
check(void) { std::cout << typeid(T).name(); }
~check(void) { std::cout << std::endl; }
};
#define CHECK_TYPE__(OPT) \
template <typename T> \
struct check<T OPT> : check<T> \
{ \
check(void) { std::cout << " "#OPT; } \
};
CHECK_TYPE__(const)
CHECK_TYPE__(volatile)
CHECK_TYPE__(const volatile)
CHECK_TYPE__(&)
CHECK_TYPE__(&&)
CHECK_TYPE__(*)
int main(void)
{
check<const volatile void * const*&>();
system("pause");
return 0;
}
è¾åºç»æï¼vcï¼ï¼
void const volatile * const * &
å¾æ¼äº®ï¼æ¯ä¸æ¯ï¼å½ç¶ï¼å¨gccéè¿æ ·è¾åºï¼voidä¼åævï¼æ以gccä¸é¢è¦è¿æ ·åcheck模æ¿ï¼
template <typename T>
struct check
{
check(void)
{
char* real_name = abi::__cxa_demangle(typeid(T).name(), nullptr, nullptr, nullptr);
std::cout << real_name;
free(real_name);
}
~check(void) { std::cout << std::endl; }
};
äºãä¿ååè¾åºå符串
æ们å¯ä»¥ç®åçè¿æ ·ä¿®æ¹check让å®åæ¶æ¯ævcågccï¼
template <typename T>
struct check
{
check(void)
{
# if defined(__GNUC__)
char* real_name = abi::__cxa_demangle(typeid(T).name(), nullptr, nullptr, nullptr);
std::cout << real_name;
free(real_name);
# else
std::cout << typeid(T).name();
# endif
}
~check(void) { std::cout << std::endl; }
};
ä½æ¯å°ç®å为æ¢ï¼checkçè¾åºç»æé½æ¯æ æ³ä¿åçãæ¯è¾å¥½çæ¹å¼æ¯å¯ä»¥åtypeid(T).name()ä¸æ ·è¿åä¸ä¸ªå符串ãè¿å°±è¦æ±checkè½å¤æç»æä¿åå¨ä¸ä¸ªstd::string对象éã
å½ç¶äºï¼æ们å¯ä»¥ç´æ¥ç»checkä¸ä¸ªâstd::string&
outâç±»åçæé å½æ°ï¼ä½æ¯è¿æ ·ä¼æè¾åºçç¶æ管çãå符çæå°é»è¾ççé½æå¨ä¸èµ·ãå æ¤ï¼æ¯è¾å¥½ç设计æ¹æ³æ¯å®ç°ä¸ä¸ªoutputç±»ï¼è´è´£è¾åºåç»´æ¤
ç¶æãæ们å°åé¢å°±ä¼æ
¢æ
¢æè§å°è¿æ ·åç好å¤å¨åªéã
outputç±»çå®ç°å¯ä»¥æ¯è¿æ ·ï¼
class output
{
bool is_compact_ = true;
template <typename T>
bool check_empty(const T&) { return false; }
bool check_empty(const char* val)
{
return (!val) || (val[0] == 0);
}
template <typename T>
void out(const T& val)
{
if (check_empty(val)) return;
if (!is_compact_) sr_ += " ";
using ss_t = std::ostringstream;
sr_ += static_cast<ss_t&>(ss_t() << val).str();
is_compact_ = false;
}
std::string& sr_;
public:
output(std::string& sr) : sr_(sr) {}
output& operator()(void) { return (*this); }
template <typename T1, typename... T>
output& operator()(const T1& val, const T&... args)
{
out(val);
return operator()(args...);
}
output& compact(void)
{
is_compact_ = true;
return (*this);
}
};
è¿ä¸ªå°å·§çoutputç±»è´è´£èªå¨ç®¡çè¾åºç¶æï¼æ¯å¦å¢å ç©ºæ ¼ï¼åè¾åºçç±»å转æ¢ï¼ä½¿ç¨std::ostringstreamï¼ã
ä¸é¢çå®ç°éæ两个æ¯è¾æææçå°æ¹ã
ä¸æ¯operator()çåæ³ï¼éç¨äºåå模æ¿ãè¿ç§åæ³è®©æ们å¯ä»¥è¿æ ·ç¨outputï¼
output out(str);
out("Hello", "World", 123, "!");
è¿ç§åæ³æ¯coutçæµæä½ç¬¦èæå¤äºã
äºæ¯operator()åcompactçè¿åå¼ãå½ç¶ï¼è¿éå¯ä»¥ç´æ¥ä½¿ç¨voidï¼ä½æ¯è¿ä¼é æä¸äºéå¶ã
æ¯å¦è¯´ï¼æ们æ³å¨ä½¿ç¨operator()ä¹å马ä¸compactå¢ï¼è¥è®©å½æ°è¿åèªèº«å¯¹è±¡çå¼ç¨ï¼å°±å¯ä»¥è®©outputç¨èµ·æ¥é常顺æï¼
output out(str);
out.compact()("Hello", "World", 123, "!").compact()("?");
checkçå®ä¹åCHECK_TYPE__å®åªéè¦ç¥ä½ä¿®æ¹å°±å¯ä»¥ä½¿ç¨outputç±»ï¼
template <typename T>
struct check
{
output out_;
check(const output& out) : out_(out)
{
# if defined(__GNUC__)
char* real_name = abi::__cxa_demangle(typeid(T).name(), nullptr, nullptr, nullptr);
out_(real_name);
free(real_name);
# else
out_(typeid(T).name());
# endif
}
};
#define CHECK_TYPE__(OPT) \
template <typename T> \
struct check<T OPT> : check<T> \
{ \
using base_t = check<T>; \
using base_t::out_; \
check(const output& out) : base_t(out) { out_(#OPT); } \
};
为äºè®©å¤é¨ç使ç¨ä¾æ§ç®æ´ï¼å®ç°ä¸ä¸ªå¤æ·å½æ°æ¨¡æ¿æ¯å¾èªç¶çäºæ
ï¼
template <typename T>
inline std::string check_type(void)
{
std::string str;
check<T> { str };
return std::move(str);
}
int main(void)
{
std::cout << check_type<const volatile void * const*&>() << std::endl;
system("pause");
return 0;
}
温馨提示:内容为网友见解,仅供参考
如何在C++中获得完整的类型名称
如果直接在typeid的结果上加上被丢弃的信息,对于一些类型而言(如函数指针引用)得到的将不是一个正确的类型名称。想要获得一个类型的完整名称,并且获得的名称必须要是一个正确的类型名称,应该怎样做呢?一、如何检查C++中的类型我们需要一个泛型类,用特化\/偏特化机制静态检查出C++中的各种类型,并且不能忽略掉类型限定...
C++ 中的typeid().name()只输出一个字符是怎么回事?
gcc就是那样的,只输出类型名的第一个字符,要输出完整的名字可以这样:include <iostream> include <typeinfo> include <cxxabi.h> \/\/使用abi using namespace std;int main(){ cout<<abi::__cxa_demangle(typeid(int).name(),0,0,0 )<<endl;return 0;} ...
C++中如何把过长的double类型以完整的形式显示呢?
有格式设置的。如果你用cout输出,用这个设置:cout <<setprecision(n)n是有效数字,你要显示20位,n就是20 如果你用printf 比方输出a变量 printf("%m.nf",a);m是总宽度,你可以设置大一些,n是小数位数,设置个3或者6
c++命名规范中,int[]以什么开头??
三、 类的成员变量以m_开头,后面为变量,变量同时还要加前缀。CString m_strName; \/\/m_开头+类型前缀+名称 四、 定义一个变量,为了简化,在不影响变量意义的情况下,可仅仅使用前缀。RECT rc;五、 全局变量一律以g_开头,后面为变量,变量同时还要加前缀。int g_ID; \/...
c++中的工程类型问题
\/\/ 先获得当前工作目录的全路径 ―getcwd(path_search,―MAX―PATH); \/\/ 再获得文件的完整的路径名(包含文件的名称) strcat(path_search,〃\\\\〃); strcat(path―search,filestruct.name); MessageBox(path_search); \/\/输出显示 } } \/\/ 继续对当前目录中的下一个子目录或文件进行与上面同样的查找 whil...
C++报错E0852:表达式必须是指向完整对象类型的指针?
c++多文件编程,每有一个自定义cpp文件,应对应一个.h头文件 在使用其他cpp文件中的类时,需要引入头文件 文件导入时,应该目录对应,如src下的目录,应该下 #include<src\/XXX.h> 如果不做目录的指明,可以通过配置编译参数来指定明路,否则会找不到 如果出现了重名,会报编译错误,因为存在二义性 ...
C++代码输入中出现不允许出现不完整的类型
你在CSceneView类定义之前,只是声明了CSceneList类,而没有定义它,例如:class CSceneList;class CSceneView { ... CSceneList list1; \/\/ 前面的 CSceneList 类只有声明而没有定义,是“不完整的类型”
C++的类型(type)
在C++中,cv qualifiers是用于指定对象的constness和volatility的修饰符,可以出现在任何类型说明符中。cv qualifiers有三种形式:const、volatile和const volatile。mutable是一种修饰符,只能用于类的成员,表示即使类是const的,该成员也可以被修改。cv void表示可能的cv qualified的void类型,实质上有四种情况...
UE5 C++中获取在蓝图中创建的DataTable和Struct的RowData
常规做法中,通过DataTable的FindRowUnchecked函数根据RowName获取Row指针,进而使用GetRowStruct函数获取蓝图中Struct的C++父类。然后,通过内部的PropertyLink迭代属性,从而获取所有属性名称。接下来,根据Class进行if判断,以识别当前属性值为声明类型。实现这一过程的关键代码如下:代码示例:通过反射机制获取Data...
c++不允许使用不完整的类型
定义对象之前,编译器必须看到完整的类定义,你的代码istringstream str( str ) 中的istringstream只是声明了,还没有定义,需要包含头文件#include <sstream>。