打印 class 标识符(如果可用)

Print class identifier if it is available

目标是创建一个(宏?)当每个 class 实例(例如,this 指针)被放置在 [=26= 中时,它会打印一个唯一标识符] 函数,在 'normal' 函数中使用时什么也没有(或其他)。 最好不要向 class 添加任何内容,但如果这是唯一的方法,我会接受它。

这是我的尝试,但它根本不喜欢使用 this(将其替换为 (void)1 可以正常工作,但我想要每个 class 的唯一标识符实例。 在 gcc 上,此错误类似于:error: invalid use of ‘this’ in non-member function,而 msvc 也有类似的错误:error C2355: 'this': can only be referenced inside non-static member functions or non-static data member initializers

无效代码:

#include <iostream>

class _detect_class_ {};
typedef int _class_sentinel_;

#define THIS_PTR std::is_same<_detect_class_, _class_sentinel_>::value ? (void*)this : nullptr
#define TRACK_THIS_OBJECT typedef _detect_class_ _class_sentinel_;

struct thisptr
{
    void* Ptr;
    thisptr(void* ptr): Ptr(ptr){;}
};

std::ostream& operator<<(std::ostream& strm, const thisptr& p)
{
    if (p.Ptr)
        strm << "Object:" << p.Ptr;
    else
        strm << "No object";
    return strm;
}

#define PRINT_ME    std::cout << thisptr(THIS_PTR) << std::endl;

struct TestStruct
{
    void Function1()
    {
        PRINT_ME;
    }
    TRACK_THIS_OBJECT
};

int main()
{
    TestStruct o1, o2;
    PRINT_ME;       // No object
    o1.Function1(); // Object: (identifier1)
    o2.Function1(); // Object: (identifier2)
    return 0;
}



最简单的技巧是在顶层用一个名为 "this".

的指针实例声明一个虚拟 class

您的宏将始终看到 "this",并且可以决定不打印,因为 this==&dummy.

缺点是 "this" 是一个保留字,可能会出现编译器警告、错误,标准编写者不会成为您的朋友。您可能会逃脱它,因为编译器会尝试保持向后支持,并且非 class 方法不需要/保留 "this".

另一个选项是一个具有复杂名称的全局符号,以及一个宏,它声明与您放入所有要跟踪的 classes 中的 class 成员相同的复杂名称.然后,当在 class 的成员函数中编译时,您的宏将看到 class 成员实例,您在其中声明了额外的符号,但在非成员函数中编译时会看到全局。

最便宜的声明符号是枚举,因为它们只是常量,但是当有很多 class 变体时,如何区分全局变体和 class 变体?您当然可以使用 typeid 名称作为包含 class.

的同义词

这些是我对它们的价值的想法。

下一个最便宜的可能是一个内联成员函数,也许还有一个内联静态成员函数和一个全局函数,它可以 return 您的唯一标识符(它们的 this 指针,也许还有它们的 typeid 对象) .

更简单的解决方案是在不同上下文中使用不同命名版本的日志记录宏。当你用错的时候,编译器会"help"你。

我更改您的代码以添加空成员 (C++20) 以获得预期输出:

_detect_class_ m; // To avoid error in THIS_PTR.

#define TRACK_THIS_OBJECT using _class_sentinel_ = _detect_class_; \
                          [[no_unique_address]]_detect_class_ m;

#define THIS_PTR std::is_same<_detect_class_, _class_sentinel_>::value ? &m : nullptr

Demo

也许这对于高级 C++ 专家来说太简单了

// this is in header pretty_print.h
#include <iostream>
inline void pretty_print() {}

#define PRINTABLE                                                              \
  void pretty_print() { std::cout << this << std::endl; }
#define PRINT_ME pretty_print()
// end of header

// #include "pretty_print.h"
void moo() { PRINT_ME; }

struct Foo {
  PRINTABLE

  void foo() { PRINT_ME; }
};

int main() {
  PRINT_ME;
  moo();
  Foo().foo();
}