简体   繁体   English

为此缺少 std::forward 之类的东西

[英]Missing something like std::forward for this

I believe I understand the concept of perfect forwarding in C++.我相信我理解C++中完美转发的概念。 But I'm missing something similar for "this".但我错过了“这个”类似的东西。 Let's have:让我们:

class X {
  std::vector<int> vec;
public:
  std::vector<int> const &getVec() const & { return vec; }
  std::vector<int> &      getVec() &       { return vec; }
  std::vector<int>        getVec() &&      { return std::move(vec); }
};

As std::forward() compresses similar definitions for parameters, I'd like to have something similar for "this".由于std::forward()压缩了类似的参数定义,我想为“this”提供类似的东西。 Something like:就像是:

class X {
  std::vector<int> vec;
public:
  auto &&getVec() /*???const &*/ { return thisForward(vec); }
};

Is something like the above possible (or available in STL or boost)?是否可能出现上述情况(或在 STL 或 boost 中可用)? Or, at least, is there some workaround?或者,至少,有一些解决方法吗?

Plus an additional question (just for verification), does my 3 overloads of getVec() above make a sense?加上一个额外的问题(仅用于验证),我上面的 3 个getVec()重载有意义吗? Is it okay (for optimization reasons) to have such 3 overloads?有这样的3个重载可以(出于优化原因)吗? (Assume "X" is a container-like class.) (假设“X”是一个类似容器的 class。)

For C++20, you can get close but I don't see how doing exactly what you ask is possible.对于 C++20,你可以接近,但我不明白如何完全按照你的要求去做。

If you are willing to turn get into a static/friend function it works.如果您get变成静态/朋友 function 它可以工作。 I couldn't get the repetition of a helper type down to zero, but maybe this can be improved on.我无法将辅助类型的重复次数降至零,但也许可以对此进行改进。 If you are willing to pay a reference member, this can likely be achieved with a wrapper but that wrapper would have to store a reference to the member.如果您愿意支付引用成员的费用,这可能会通过包装器来实现,但该包装器必须存储对该成员的引用。

#pragma once
#include <type_traits>

template <typename T>
concept lvalue = std::is_lvalue_reference_v<T> && !std::is_const_v<std::remove_reference_t<T>>;
template <typename T>
concept lcvalue = std::is_lvalue_reference_v<T> && std::is_const_v<std::remove_reference_t<T>>;

template <typename T, typename R>
struct RT {
  using type = R;
};
template <lvalue T, typename R>
struct RT<T,R> {
  using type = std::add_lvalue_reference_t<std::remove_const_t<R>>;
};
template <lcvalue T, typename R>
struct RT<T,R> {
  using type = std::add_lvalue_reference_t<std::add_const_t<R>>;
};

template <typename T, typename R>
using RT_t = typename RT<T,R>::type;

Example:例子:

#include <vector>
#include <cassert>
#include "rt.h"

namespace {
  struct X {
    std::vector<int> v;

    template <typename Self>
    friend RT_t<Self,std::vector<int>> get(Self&& self) {
      return std::forward<RT_t<Self,std::vector<int>>>(self.v);
    }
  };
}

int main() {
  X x{std::vector{1,2,3}};
  assert(x.v.size() == 3);
  X& xr = x;
  get(xr).push_back(1);
  assert(x.v.size() == 4);
  //X const& xc = x;
  //get(xc).push_back(1); // does not compile
  {
    std::vector<int> vec = get(std::move(x));
    assert(vec.size() == 4);
  }
  assert(x.v.size() == 0);
}

So, downsides:所以,缺点:

  • One has to write get(x) instead of x.get()必须写get(x)而不是x.get()
  • When defining get one has to repeat RT_t<Self,std::vector<int>>定义get one 时必须重复RT_t<Self,std::vector<int>>

Demo on compiler explorer .编译器资源管理器上的演示

As of C++23 it will be possible to declare the this parameter explicitly .从 C++23 开始,可以显式声明 this 参数 Then you will be able to do what you are asking for:然后,您将能够做您要求的事情:

class X {
    std::vector<int> vec;
public:
    template<class Self>
    decltype(auto) getVec(this Self&& self) {
        return std::forward<Self>(self).vec;
    }
};

You can read more here .你可以在这里阅读更多。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM