在 c++ 中显示嵌套类型定义的最基本类型声明
Show most basic type declaration of nested typedefs in c++
在读取别人的代码时,除了遍历所有标头,搜索各自的定义之外,是否有一种简单的方法来展开嵌套typedef的底层类型?
例如,今天我遇到了
auto* p = new A<B::C>();
其中 B::C 在某个标头中定义为
template <typename T>
class B: public BBase {
typedef B< D<E, E> > C;
}
D 和 E 在其他地方定义。C
我可以以某种方式显示 p 实际上是A<B<D<E, E>>>
吗?
如果您不想混淆typeid
名称,另一种方法是:
template<typename> struct TC;
然后TC<A<B::C>> a;
放在某个地方,你会得到一个编译器错误,其中包含完整的推断类型。
例如:
template<typename> struct TC;
template<typename> using A = int;
using B = A<float>;
int main()
{
TC<B> a;
}
海湾合作委员会输出:
主.cpp:8:11: 错误: 聚合
TC<int> a
具有不完整的类型,无法定义
如您所见,B
被替换为A<float>
,后者在编译器错误中被替换为int
。
typeid(T).name()
.它在 Visual C++ 中为您提供了一个很好的可读类型声明。使用 g++ 编译器,您必须使用 g++ 特定的功能来解散有点神秘的结果。
为了使用typeid
必须包含<typeinfo>
标头。
g++ 名称拆解函数是从 g++ <cxxabi.h>
标头abi::__cxa_demangle
的。
示例(我必须修复您所谓的声明的各种细节):
template< class > struct A {};
template<class, class> struct D {};
struct E {};
struct BBase {};
template<class>
class B: public BBase
{
public:
using C = B< D<E, E> >;
};
#include <string>
#include <typeinfo>
using namespace std;
#ifdef __GNUC__
# include <cxxabi.h>
auto demangled( char const* name )
-> string
{
int status = 0;
char* realname = abi::__cxa_demangle( name, 0, 0, &status );
string result = realname;
free( realname );
return result;
}
#else
# include <sstream>
auto demangled( char const* name )
-> string
{
// Possibly remove all instances of "struct ", "class " and "enum "
return name;
}
#endif
#include <iostream>
auto main() -> int
{
auto* p = new A<B<int>::C>();
(void) p; // unused
cout << demangled( typeid( p ).name() ) << endl;
}
使用 g++ 输出:
A<E,>>>*
另一种方法是TartanLlama提出的技巧,即在未定义的模板中使用相关类型:
template<class> class Incomplete;
auto main() -> int
{
Incomplete< A<B<int>::C> > x;
}
使用 g++ 生成错误消息:
ar.cpp:24:36:错误:聚合"不完整<E,E>>>> x"具有不完整的类型,无法定义 不完整 ::C>> x; ^
这些是我想到的选项:
1)调试打印,可以临时添加typeid(E)等,但需要编译运行,所以不只是读取代码。
2)使用像Visual Studio,qt creator等IDE应该能够显示实际的typedefs/定义,当鼠标悬停在typedef/defines的任何用法上时。
3)使用文本编辑器,许多文本编辑器可能允许使用插件来加快搜索速度,并从符号跳转到符号以快速找到它们已定义的内容。
所以最终的答案我认为通过查看代码是没有办法知道的,这实际上是定义带来的一个问题,它稍微混淆了代码。
on gcc/clang:
#include <iostream>
#include <cxxabi.h>
#include <string>
#include <stdexcept>
#include <exception>
#include <typeinfo>
std::string demangle(const char* mangled_name)
{
using namespace std;
size_t len = 0;
int stat = 0;
struct deleter {
void operator()(const char* p) const {
if (p) {
auto p1 = const_cast<char*>(p);
free(p1);
}
}
};
using ptr_type = std::unique_ptr<const char, deleter>;
auto pname = ptr_type(abi::__cxa_demangle(mangled_name,
nullptr,
&len,
&stat),
deleter());
if (stat)
{
switch(stat) {
case -1:
throw std::bad_alloc();
break;
case -2:
throw std::logic_error("invalid name: "s + mangled_name);
break;
case -3:
throw std::invalid_argument("demangle");
default:
throw std::logic_error("unknown error code "s + to_string(stat));
}
}
return string(pname.get(), len);
}
template<class X, class Y> struct D {};
struct E {};
template <typename T>
struct B {
typedef B< D<E, E> > C;
};
int main()
{
using namespace std;
cout << demangle(typeid(B<int>::C).name()) << endl;
return 0;
}
毫无疑问,Windows将具有类似的方法来解开名称。
预期输出:
B<D<E, E> >
- 将类型声明为类型模板参数的模板参数的一部分是否合法?
- 当返回类型声明为 ListNode 时,我们是否可以返回 false<T>*
- 如何使用自定义类型声明Arduino数组?
- 将函数参数类型声明为 auto
- 使用typedef'ed返回类型声明友元函数时出现编译器错误
- 在没有标识符的情况下如何读取复杂的C++类型声明?
- 模板函数参数显式类型声明
- 使用指针遍历一系列基元类型声明?
- 字符类型声明和验证
- 使用本地类型声明的G lambda被使用但从未定义 - 确实是一个错误
- 为什么 c++ lambda 捕获不需要类型声明?
- 为什么没有"int"类型声明时输出不同?
- C++如何使用虚拟基类型声明全局静态分配的变量
- 我可以使用预处理器将一个类型声明替换为另一个类型声明吗?
- 如何将数据类型声明从.cpp文件传输到 .cu 文件
- C++17 枚举类型声明
- 条件类型声明
- 具有特定参数的特定构造函数的类型声明
- 我可以使用相同的名称为周围作用域中的类型声明成员类型别名吗
- 函数调用之前,C 类型声明