gpt4 book ai didi

c++ - 反复出现的成本难题

转载 作者:可可西里 更新时间:2023-11-01 16:29:29 26 4
gpt4 key购买 nike

我经常发现自己必须定义一个函数的两个版本,以便拥有一个常量版本和一个非常量版本(通常是 getter,但并非总是如此)。两者的区别仅在于一个的输入和输出是 const,而另一个的输入和输出是非常量。该函数的核心 - 真正的工作,是完全相同的。

然而,为了常量正确性,我需要它们。作为一个简单的实际示例,请看以下内容:

inline const ITEMIDLIST * GetNextItem(const ITEMIDLIST * pidl)
{
return pidl ? reinterpret_cast<const ITEMIDLIST *>(reinterpret_cast<const BYTE *>(pidl) + pidl->mkid.cb) : NULL;
}

inline ITEMIDLIST * GetNextItem(ITEMIDLIST * pidl)
{
return pidl ? reinterpret_cast<ITEMIDLIST *>(reinterpret_cast<BYTE *>(pidl) + pidl->mkid.cb) : NULL;
}

如您所见,它们做同样的事情。我可以选择使用更多的转换根据另一个来定义一个,如果胆量 - 实际工作不那么微不足道,这更合适:

inline const ITEMIDLIST * GetNextItem(const ITEMIDLIST * pidl)
{
return pidl ? reinterpret_cast<const ITEMIDLIST *>(reinterpret_cast<const BYTE *>(pidl) + pidl->mkid.cb) : NULL;
}

inline ITEMIDLIST * GetNextItem(ITEMIDLIST * pidl)
{
return const_cast<ITEMIDLIST *>(GetNextItem(const_cast<const ITEMIDLIST *>(pidl));
}

所以,我觉得这非常乏味和多余。但是,如果我想编写 const-correct 代码,那么我要么必须提供以上两者,要么我必须用 const-casts 乱扔我的“消费者代码”以解决只定义一个或另一个的问题.

有更好的模式吗?您认为解决此问题的“最佳”方法是什么:

  • 提供给定函数的两个拷贝 - const 和非常量版本
  • 或者只是一个版本,然后要求该代码的消费者按照他们的意愿进行转换?

或者是否有更好的方法来完全解决这个问题?是否正在针对语言本身开展工作以完全缓解或避免此问题?

对于奖励积分:

  • 你觉得这是 C++ 常量系统的不幸副产品吗
  • 或者您认为这等同于触及奥林匹斯山的高度?

编辑:

如果我只提供第一个 - 采用 const 返回 const,那么任何需要修改返回项或将返回项交给另一个将修改它的函数的消费者都必须摆脱 constness。

类似地,如果我只提供第二个定义 - 采用非常量并返回非常量,那么具有 const pidl 的消费者必须摆脱常量才能使用上述函数,老实说,它不会修改项目本身的常量。

也许更抽象是可取的:

THING & Foo(THING & it);
const THING & Foo(const THING & it);

我很想有一个结构:

const_neutral THING & Foo(const_neutral THING & it);

我当然可以这样做:

THING & Foo(const THING & it);

但这总是让我感到不快。我是说“我不会修改你的 THING 的内容,但我会在你的代码中摆脱你默默地委托(delegate)我为你赋予的常量。”

现在,一个客户有:

const THING & it = GetAConstThing();
...
ModifyAThing(Foo(it));

这是错误的。 GetAConstThing 与调用者的约定是给它一个const 引用。调用者不应修改该内容 - 仅对其使用常量操作。是的,调用者可能是邪恶的和错误的,并且抛弃了它的常量,但这只是 Evil(tm)。

对我来说,问题的症结在于 Foo 是 const 中立的。它实际上并没有修改给定的东西,但它的输出需要传播其参数的常量性。

注意:第二次编辑格式。

最佳答案

IMO 这是 const 系统的一个不幸的副产品,但它并不经常出现:只有当函数或方法给出指向某物的指针/引用时(无论它们是否修改某物,函数都不能'不要分发它没有的权利,否则 const-correctness 会严重破坏,因此这些重载是不可避免的)。

通常,如果这些函数只是一小段代码,我会重复它们。如果实现更复杂,我使用模板来避免代码重复:

namespace
{
//here T is intended to be either [int] or [const int]
//basically you can also assert at compile-time
//whether the type is what it is supposed to be
template <class T>
T* do_foo(T* p)
{
return p; //suppose this is something more complicated than that
}
}

int* foo(int* p)
{
return do_foo(p);
}

const int* foo(const int* p)
{
return do_foo(p);
}

int main()
{
int* p = 0;
const int* q = foo(p); //non-const version
foo(q); //const version
}

关于c++ - 反复出现的成本难题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1822429/

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