在c ++中显示嵌套typedef的最基本类型声明

时间:2016-01-21 10:07:05

标签: c++ typedef

在阅读其他人的代码时,是否有一种简单的方法来展开嵌套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>>>吗?

4 个答案:

答案 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> >