【问题标题】:debugging with c++ templates使用 c++ 模板进行调试
【发布时间】:2022-01-02 07:41:31
【问题描述】:

问题:我需要找到结构成员被修改的时间和地点。

我在一个大型实时系统上工作,其中部分旧系统最初是用 C 编写的。在这种情况下,结构从来都不是类,也没有私有成员,所以一切都在轻而易举。

我有很好的分析和调试工具,但是一个结构成员的设置避开了静态分析,gdb watch 很困难,因为我们有太多的结构实例。在实时系统上运行 gdb 也会产生奇怪的结果。

这是我用来将成员声明从int 更改为报告分配的模板实例的模板。除了两种情况外,这在所有情况下都有效。

  • 我无法编写允许将模板的值转换为枚举的重载(我可以将其转换为浮点数)。这是通过添加 * 来解决的,从而强制使用 * 运算符。但是,如果我可以声明一个可以避免这种情况的重载,那将是最好的。幸运的是,代码中只有一个实例。请参阅下面的错误。
  • 最初我有一个我认为是引用运算符T& operator&(),但最终在写这篇文章时发现operator T& () 是正确的解决方案。为什么第一个不起作用?
    #include <stdio.h>
    
    template <typename T> class TraceType {
    private:
        T value;
    public:
        TraceType()             { value = (T)~0; }
        T operator=(T v)        { notify(v); value = v; return v; }
        T operator->() const    { return value; }
        T operator*() const     { return value; }
        operator T& ()          { return value; }
        operator T () const     { return value; }
        bool operator==(const T rhs) const
                                { return value == rhs; }
        void notify(T);
    };
    
    struct Foo {
        int x;
        // this should have been the only change necessary
        // need to find when/where this gets changed
        // int y;
        TraceType<int> y;
        int z;
    };
    
    const char* getStackTrace() { return "<stack trace"; }
    
    template<> void TraceType<int>::notify(int v)
        { printf("y<--%d %s\n", v, getStackTrace()); }
    
    enum Special { one, two, three };
    
    int main(int argc, char** argv)
    {
        Foo foo;
        foo.x = 1;
        foo.y = 2;
        foo.z = 3;
    
        Foo* fooPtr = &foo;
        // error: invalid cast from type ‘TraceType<int>’ to type ‘Special’
        // Special xxx = (Special)fooPtr->y;
    
        Special xxx = (Special)*fooPtr->y; // this works
        float yyy = (float)fooPtr->y;      // this works
    
        int& refToY = foo.y;               // this works
    }

【问题讨论】:

    标签: c++ templates overloading


    【解决方案1】:

    添加模板化转换运算符:

    template <typename T> class TraceType {
    private:
        T value;
    public:
        TraceType()             { value = (T)~0; }
        T operator=(T v)        { notify(v); value = v; return v; }
        T operator->() const    { return value; }
        T operator*() const     { return value; }
        operator T& ()          { return value; }
        operator T () const     { return value; }
        bool operator==(const T rhs) const
                                { return value == rhs; }
        // Templated conversion operator
        template <class U> operator U() const { return static_cast<U>(value); }
        void notify(T);
    };
    

    【讨论】:

      【解决方案2】:

      关于您尝试实现:T&amp; operator&amp;() ...
      operator&amp;()(不带参数)是 address-of 运算符。


      一般情况下,不应重载地址运算符。


      但是,如果你这样做了,那么让它返回所代表对象的地址。

      T * operator & () { return &value; }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-04-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-04-23
        • 2015-01-11
        相关资源
        最近更新 更多