【问题标题】:How can I create a any-type pointer constant in C++?如何在 C++ 中创建任意类型的指针常量?
【发布时间】:2021-01-22 10:20:33
【问题描述】:

我想要一个可以分配给任何指针的整数常量。我打算使用这个特殊值来标记最近删除的指针(仅用于调试目的)。我想创建一个结构,然后用一个处理所有可能的 LHS 指针和我的 RHS 自定义类型的模板覆盖赋值 operator=。

但是,afaik 除了作为成员之外,没有办法重载赋值运算符 = 的左侧。我想出了这个(非编译)代码,如果不是语言边界,它会产生预期的结果。

struct TPointerConst
{
    TPointerConst(uint64 InValue) : Value(InValue) { }

    template <typename TPtr>
    friend TPtr& operator=(TPtr& Left, const TPointerConst& Right);
    
private:
    uint64 Value;
};

template <typename TPtr>
TPtr& operator=(TPtr& Left, const TPointerConst& Right) {
    return Left = (TPtr)Right.Value;
}

constexpr TPointerConst DELETED_PTR = 0xFADE404;

/* ... */

int* intPtr = DELETED_PTR;
float* fltPtr = DELETED_PTR;

我还考虑过将值强制转换为 nullptr_t(当我想到它时,这似乎很奇怪)只是为了满足编译器,但我怀疑你不能将任何东西强制转换为 nullptr_t。

我想尽可能地避免使用宏,但是如果我为这个特性留下一个类似 const 的宏(比如好的,旧的 NULL),那也不会太糟糕。我的目标至少是 C++11,所以任何与现代 C++ 相匹配的东西都会令人满意。

【问题讨论】:

  • 总是使用std::unique_ptr(或共享)然后整个问题消失(以及std::vector 用于本地缓冲区)怎么样?
  • @RichardCritten 我打算将此功能用作我自己的共享指针和自定义分配器的调试工具。我实际上是在尝试从我的引擎中的游戏程序员那里抽象出你在谈论的东西,所以它几乎是关于实现这两者。
  • 你描述的很像nullptr
  • 你想发明void *吗?

标签: c++ pointers templates constants


【解决方案1】:

我设法通过重载转换运算符而不是赋值来处理这个问题。老实说,我认为那些不可能是模板,结果我错了。这是一个概念证明,我将在其中添加静态断言以使其更安全。

struct TPointerConst
{
    constexpr TPointerConst(uint64 InValue) noexcept : Value(InValue) { }

    template <typename TPtr>
    constexpr operator TPtr() const { 
        return (TPtr)Value;
    }
    
private:
    uint64 Value;
};

constexpr TPointerConst DELETED_PTR(0x001);

int main()
{
  int* intPtr = DELETED_PTR;
  float* fltPtr = DELETED_PTR;
  
  cout << intPtr << endl << fltPtr;
}

【讨论】:

    【解决方案2】:

    template&lt;typename T&gt; operator T*() 会很有用:

    struct TPointerConst{
        TPointerConst(std::uintptr_t v) :value(v){};
    
        template<typename T>
        operator T*() const{
            return reinterpret_cast<T*>(value);
        }
    private:
        std::uintptr_t value;
    };
    
    
    
    int main(){
        TPointerConst a = 0xCDCDCDCD;
        int* b = a;
    }
    

    【讨论】:

    • 是的,在您发布解决方案前几分钟,我得出了同样的结论:) 我还决定使用构造函数 constexpr,这样我就可以在任何地方使用仅标题的 constexpr。谢谢!
    • 运算符 T*(带星号)是否仅在我尝试转换为指针类型时才匹配?这将使我免于那些 static_asserts
    • @noisycat 是的,模板参数取决于它将被转换为什么类型。见en.cppreference.com/w/cpp/language/cast_operator。如果你想限制转换,使用SFINAE而不是static_assert会更好。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-16
    • 2016-07-25
    • 1970-01-01
    相关资源
    最近更新 更多