gpt4 book ai didi

c++ - 如何使用类的常量裁判和非常量裁判版本避免 DRY?

转载 作者:行者123 更新时间:2023-12-04 12:15:32 27 4
gpt4 key购买 nike

我有一些看起来像这样的类(class):

struct A {
void *stuff;
int x;

int foo() const;
}
我有一些采用这种类型参数的函数,例如
int bar(A a1, A2 a2);
int baz(A2 a2);
问题是,并非所有这些函数实际上都改变了 a2.stuff 中的任何内存。 ;然而 - 我不能接受 const void*和一个 int , 构造一个 A 并将其传递给此类函数。或者更确切地说,我可以,但只能使用 const_cast<>这真的不是你生活的方式。另外,我很容易混淆并通过我的 const_cast<> 'ed A 到一个实际修改数据的函数 A::stuff .
所以,我决定我想要一个“常数 A”。不是字段不可变的 A - 通过它你不会改变东西指向的 A 。
如果 A 以某种方式被模板化,即如果它是某种类型的 T - 那么没问题,你更换 A<void>与 A <const void>而 Bjarne 是你的叔叔。但是... A 不是模板化的。我不想让它模板化,因为我不想 A<int>的或类似的东西存在。
所以我该怎么做?
天真的方法是几乎为 const_A 复制 A 的定义。 :
struct const_A {
void const *stuff;
int x;

int foo() const;
}

struct A {
void *stuff;
int x;

int foo() const;
operator const_A() const { return const_A { stuff, x }; }
}
但这是重复的,如果我有 20 种方法,重复起来就更烦人了。
没有大量样板、私有(private)成员、所有ctors 的实现等的解决方案的加分点。

最佳答案

基于 std::experimental::propagate_const 思想的解决方案:

namespace detail {
struct const_propagating_void_ptr {
void* ptr;

operator void *() { return ptr; }
operator void const *() const { return ptr; }
};
} // namespace detail

struct A {
detail::const_propagating_void_ptr stuff_;
int x;

int foo() const;
void * stuff() { return stuff_; }
void const * stuff() const { return stuff_; }
};
优点:
  • Rule of Zero(也称为 C++ Core Guideline C.20)FTW。
  • 事实上,A 和类似指针的类只是普通的旧结构!
  • 你可以在其他地方重用类似指针的类(甚至模板化它),所以它有更多的文本但不是那么多。

  • 缺点:
  • const A a1 {my_ptr, 123};
    A a2 {a1};
    *a2.stuff() = 456; // ... and a1's pointer is used for write access :-(
    这个 compiles without warnings 。感谢@AyxanHaqverdili 指出这一点。
  • 无法从 const Aconst void*(没有 const_cast'ing)构造 int
  • 实际上并没有保护 const-propagator 免受直接访问;但至少这种访问必须是明确的。我们可以通过实际使用 std::experimental::propagate_const 来禁用它,它可能有一个 protected 数据成员,覆盖赋值和移动赋值运算符等。

  • 问: 为什么不在 A 中使用 getter 并使用 void*
    A: A 的用户很容易犯访问 A::stuff_ 而不是 A::stuff() 的错误。如果那只是一个 void * ,那么意外写入 A::stuff_ 的几率会很高。但是使用此解决方案,要获得 void*,您需要编写: A::stuff_::ptr ,并且没有人会错误地编写 my_a.stuff.ptr 而不是 my_a.stuff()

    关于c++ - 如何使用类的常量裁判和非常量裁判版本避免 DRY?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68226516/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com