如何在一个声明中(模板地)声明常量和非常量运算符重载?

问题描述 投票:0回答:1

简介

我正在编写一个类

stalker<Obj>
,其中包含类型为
Obj
的变量。我希望
stalker<Obj>
假装它与
Obj
变量几乎相同(从用户的角度来看)。然而,我们对
Obj
几乎一无所知。

因此,我尝试通过重载所有可能的运算符(文字运算符除外)来实现此目的,并且还针对其他意外行为重载强制转换运算符。这会创建很多代码:

template <typename Obj>
class stalker {
  Obj obj;

 public:
  operator Obj&() {
    return obj;
  }

  template <typename Arg>
  decltype(auto) operator[](Arg&& arg) {
    return obj[std::forward<Arg>(arg)];
  }

  // and other 20+ overloads...
};

第一个问题是

Obj::operator[]
可以返回
void
我不想重复我的代码。这是我解决它的方法:

template <typename Arg>
decltype(auto) operator[](Arg&& arg) {
  if constexpr (std::is_same_v<void, decltype(std::declval<Obj&>()[std::forward<Arg>(arg)])>) {
    obj[std::forward<Arg>(arg)];
  } else {
    return obj[std::forward<Arg>(arg)];
  }
}

这段代码看起来已经很重了(你知道更简单的方法吗?)。

问题

stalker<Obj>
可以标记为
const
或者它具有
const
类型:
stalker<const Obj>
。然后我们需要所有运算符的
const
版本。

我们如何在

one
声明 inside 类中模板重载
void
/
non-void
const
/non-const 运算符?

或者是否有更好的方法来实现与

stalker<Obj>
相同的
Obj
行为?

方法

CPP参考有:non-duplicate code of both const & non-const versions(帮助我理解这一点)。

另一个网站提供:https://www.cppstories.com/2020/11/share-code-const-nonconst.html/。但是,

mutable
限定符或
const_cast
不是解决方案。我几乎不理解模板部分,但似乎通过这种方式我们不再假装为
Obj
(我们需要在某些函数中传递
obj
)。

c++ methods constants function-declaration
1个回答
0
投票

第一个问题是 Obj::operator[] 可能返回 void。

没问题,返回

void
有效。

template <typename Arg>
decltype(auto) operator[](Arg&& arg) { return obj[std::forward<Arg>(arg)]; }

还可以。

我们如何在类内的一个声明中模板地重载 void/non-void 和 const/non-const 运算符?

如上所示,void/non-void 没有问题。 尽管如此,仍然存在 const/volatile 和参考 cartesion 产品重载。

C++23之前,你必须全部编写。

自 C++23 起,就有了“推导

this
”,它允许只写

template <typename Self, typename Arg>
decltype(auto) foo(this Self&& self, Arg&& arg) {
    return std::forward<Self>(self).obj[std::forward<Arg>(arg)];
}

© www.soinside.com 2019 - 2024. All rights reserved.