在阅读其他人的代码时,是否有一种简单的方法来展开嵌套typedef的基础类型,除了遍历所有标题,搜索相应的定义?
E.g。今天我遇到了
auto* p = new A<B::C>();
其中B :: C在某些标题中定义为
template <typename T>
class B: public BBase {
typedef B< D<E, E> > C;
}
和D和E在其他地方定义。 ç
我可以以某种方式显示p实际上是A<B<D<E, E>>>
吗?
答案 0 :(得分:1)
您可以使用typeid(T).name()
。它在Visual C ++中为您提供了一个很好的可读类型声明。使用g ++编译器,您必须使用特定于g ++的功能来消除有些神秘的结果。
要使用typeid
,您必须包含<typeinfo>
标题。
g ++名称demangling函数是abi::__cxa_demangle
from the g++ <cxxabi.h>
header。
示例(我必须修复所谓声明的各种细节):
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<B<D<E, E> > >*
另一种选择是trick presented by TartanLlama,在未定义的模板中使用相关类型:
template<class> class Incomplete;
auto main() -> int
{
Incomplete< A<B<int>::C> > x;
}
使用g ++生成错误消息:
ar.cpp:24:36: error: aggregate 'Incomplete<A<B<D<E, E> > > > x' has incomplete type and cannot be defined Incomplete< A<B<int>::C> > x; ^
答案 1 :(得分:1)
如果您不想解冻//declare SkinnedMeshRenderer
public SkinnedMeshRenderer smr;
//initialization
//previously put the initialization on Start(), but I try to put it on Awake() to make the initialization a bit sooner
void Awake ()
{
if (smr == null) smr = GetComponent<SkinnedMeshRenderer>();
smr.sharedMesh = (Mesh)Instantiate(smr.sharedMesh);
}
// Remember the index and ratio used last time to highlight.
private int prevIndex = -1;
private int prevRatio = -1;
// Change vertex colors highlighting given bone
public void Highlight(int index,double ratio = 1 )
{
// If nothing changed, no need to highligh again - everything is already
// highlighted. Break function execution.
if (index == prevIndex && ratio == prevRatio) return;
Transform[] bones = null;
switch (index)
{
case (int)Skeleton.Head: bones = head; break;
case (int)Skeleton.UpperBody: bones = upperBody; break;
case (int)Skeleton.LowerBody: bones = lowerBody; break;
case (int)Skeleton.RightUpperArm: bones = upperArmRight; break;
case (int)Skeleton.RightLowerArm: bones = lowerArmRight; break;
case (int)Skeleton.RightHand: bones = handRight; break;
case (int)Skeleton.LeftUpperArm: bones = upperArmLeft; break;
case (int)Skeleton.LeftLowerArm: bones = lowerArmLeft; break;
case (int)Skeleton.LeftHand: bones = handLeft; break;
case (int)Skeleton.RightUpperLeg: bones = upperLegRight; break;
case (int)Skeleton.RightLowerLeg: bones = lowerLegRight; break;
case (int)Skeleton.RightFoot: bones = footRight; break;
case (int)Skeleton.LeftUpperLeg: bones = upperLegLeft; break;
case (int)Skeleton.LeftLowerLeg: bones = lowerLegLeft; break;
case (int)Skeleton.LeftFoot: bones = footLeft; break;
default: break;
}
//Debug.Assert(smr != null);
if (smr != null)
{
var mesh = smr.sharedMesh;
var weights = mesh.boneWeights;
var colors = new Color32[weights.Length];
var sums = new float[weights.Length];
for (int j= 0; j<bones.Length; j++)
{
var idx = GetBoneIndex (bones [j]);
for (int i = 0; i < colors.Length; ++i)
{
float sum = 0;
if (weights [i].boneIndex0 == idx && weights [i].weight0 > 0)
sum += weights [i].weight0;
if (weights [i].boneIndex1 == idx && weights [i].weight1 > 0)
sum += weights [i].weight1;
if (weights [i].boneIndex2 == idx && weights [i].weight2 > 0)
sum += weights [i].weight2;
if (weights [i].boneIndex3 == idx && weights [i].weight3 > 0)
sum += weights [i].weight3;
sums [i] += sum;
colors [i] = Color32.Lerp (regularColor, highlightColor, sums [i] * (float)ratio);
}
//Debug.Log("bone index:\t"+bones[j].ToString());
}
mesh.colors32 = colors; // Finally, do it once
}
else Debug.Log("smr null");
}
名称,另一种选择是:
typeid
然后将template<typename> struct TC;
放在某处,你会得到编译器错误,其中包含完整的推导类型。
例如:
TC<A<B::C>> a;
GCC产出:
main.cpp:8:11:错误:聚合
template<typename> struct TC; template<typename> using A = int; using B = A<float>; int main() { TC<B> a; }
类型不完整且无法定义
正如您所看到的,TC<int> a
替换了B
,它在编译器错误中替换了A<float>
。
答案 2 :(得分:0)
这些是我想到的选择:
1)调试打印,你可以临时添加typeid(E)等,但需要编译和运行,所以不只是阅读代码。
2)使用像visual studio,qt creator等IDE,应该能够显示当鼠标悬停在typedef / definitions的任何用法上时实际的typedef / defined。
3)使用文本编辑器,许多文本编辑器可能允许使用插件来加速搜索并从符号跳转到符号,以便在定义它们时快速查找。
所以最后的答案我认为通过查看代码无法知道这一点,这实际上是定义带来的一个问题,它会稍微混淆代码。
答案 3 :(得分:0)
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> >