如何 std::forward( *this )

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

因为我想重载成员函数的所有 cv 和引用资格,所以我自己编写了以下宏:

#define DEFINE_FUNCTION(sig , functionality) \
    sig & { functionality; } \
    sig && { functionality; } \
    sig const & { functionality; } \
    sig const && { functionality; } \
    sig volatile & { functionality; } \
    sig volatile && { functionality; } \
    sig const volatile & { functionality; } \
    sig const volatile && { functionality; }

不幸的是,如果我想以转发方式返回

*this
(即保留返回类型中
this
指针的所有引用和 cv 限定,看来,我必须手动编写所有 8 个重载.

现在回答我的问题: 是否可以以通用的方式获取

*this
的简历和参考合格类型?

我尝试过

decltype(auto)
作为返回类型并且

return std::forward<decltype(*this)>(*this);

但显然,结果表达式始终解析为左值引用,即使在

&&
限定函数的情况下也是如此。

你能帮我吗?

c++ c++14
2个回答
5
投票

你需要的是一个朋友。

struct blah {
  decltype(auto) foo() & { return do_foo(*this); }
  decltype(auto) foo() && { return do_foo(std::move(*this)); }
  decltype(auto) foo() const& { return do_foo(*this); }
  decltype(auto) foo() const&& { return do_foo(std::move(*this)); }
  decltype(auto) foo() const volatile& { return do_foo(*this); }
  decltype(auto) foo() const volatile&& { return do_foo(std::move(*this)); }
  decltype(auto) foo() volatile& { return do_foo(*this); }
  decltype(auto) foo() volatile&& { return do_foo(std::move(*this)); }

  blah( const volatile blah&& b ) {}
  blah( const volatile blah& b ) {}
  blah( const blah& b ) = default;
  blah( blah&& b ) = default;
  blah() = default;

  template<class Self>
  friend blah do_foo(Self&& self) {
    std::cout << "Is reference:" << std::is_reference<Self>::value << "\n";
    std::cout << "Is const:" << std::is_const<std::remove_reference_t<Self>>::value << "\n";
    std::cout << "Is volatile:" << std::is_volatile<std::remove_reference_t<Self>>::value << "\n";
    return decltype(self)(self);
  }
};

测试代码:

blah{}.foo();
blah tmp;
tmp.foo();
const blah tmp2;
tmp2.foo();

输出:

Is reference:0
Is const:0
Is volatile:0
Is reference:1
Is const:0
Is volatile:0
Is reference:1
Is const:1
Is volatile:0

实例.

使用宏实现转发给好友的方法,手动编写好友。如果你能接受完美转发的缺点的话,转发给朋友的方法甚至可以是

template<class...Args>

减少在宏中运行的代码是值得的。

#define RETURNS(...) \
  noexcept(noexcept(__VA_ARGS__)) \
  -> decltype( __VA_ARGS__ ) \
  { return __VA_ARGS__; }

#define FORWARD_METHOD_TO_FRIEND( NAME, SELF, REF_QUAL, HELPER_NAME ) \
  template<class...Args>
  auto NAME( Args&&... args ) REF_QUAL \
  RETURNS( HELPER_NAME( SELF, std::forward<Args>(args)... ) )

#define FORWARD_CV_METHOD_TO_FRIEND( NAME, SELF, REF_QUAL, HELPER_NAME ) \
  FORWARD_METHOD_TO_FRIEND( NAME, SELF, REF_QUAL, HELPER_NAME ) \
  FORWARD_METHOD_TO_FRIEND( NAME, SELF, const REF_QUAL, HELPER_NAME ) \
  FORWARD_METHOD_TO_FRIEND( NAME, SELF, const volatile REF_QUAL, HELPER_NAME ) \
  FORWARD_METHOD_TO_FRIEND( NAME, SELF, volatile REF_QUAL, HELPER_NAME )

#define FORWARD_SELF_TO_FRIEND( NAME, HELPER_NAME ) \
  FORWARD_CV_METHOD_TO_FRIEND( NAME, *this, &, HELPER_NAME ) \
  FORWARD_CV_METHOD_TO_FRIEND( NAME, std::move(*this), &&, HELPER_NAME ) 

将上面的

blah
缩短为:

struct blah {
  FORWARD_SELF_TO_FRIEND( foo, do_foo )
  // ...
  template<class Self>
  void do_foo( Self&& self )
  {
    // some_blah.foo() invokes do_foo passing it
    // self with the proper qualifications
  }
};

替换(并改进)所有

foo()
方法。

some_blah.foo()
现在调用
do_foo( some_blah )
,并具有适当的 CV 和 L/R 值资格,并且
some_blah
上没有例外。

constexpr
可能需要一些爱才能正确,因为我们现在在 C++ 中没有条件 constexpr 测试。也许简单地在生成的模板
constexpr
中声明
foo
是正确的,但我对这个问题很模糊。


0
投票

在 GCC 的前沿(> 13.2),您可以使用 推导

this
:

#include <iostream>
#include <utility>


struct blah {
  template<typename Self>
  decltype(auto) foo(this Self&& self) { 
    std::cout << "Is reference:" << std::is_reference<Self>::value << "\n";
    std::cout << "Is const:" << std::is_const<std::remove_reference_t<Self>>::value << "\n";
    std::cout << "Is volatile:" << std::is_volatile<std::remove_reference_t<Self>>::value << "\n";
    return decltype(self)(self);
  }
  blah( const volatile blah&& b ) {}
  blah( const volatile blah& b ) {}
  blah( const blah& b ) = default;
  blah( blah&& b ) = default;
  blah() = default;
};
© www.soinside.com 2019 - 2024. All rights reserved.