首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何性病::转发(*此)

如何性病::转发(*此)
EN

Stack Overflow用户
提问于 2017-11-06 15:24:33
回答 1查看 420关注 0票数 6

由于我希望重载成员函数的所有cv和引用资格,所以我给自己编写了以下宏:

代码语言:javascript
复制
#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-pointer的所有引用和cv限定,我似乎必须手动编写所有8个重载。

现在来问我的问题:是否有可能以通用的方式获得cv和引用合格类型的*this

我尝试过decltype(auto)作为返回类型,并且

代码语言:javascript
复制
return std::forward<decltype(*this)>(*this);

但是显然,结果表达式总是解析为lvalue引用,即使在&&-qualified函数的情况下也是如此。

你能帮帮我吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-11-06 15:41:12

你需要的是一个朋友。

代码语言:javascript
复制
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);
  }
};

测试代码:

代码语言:javascript
复制
blah{}.foo();
blah tmp;
tmp.foo();
const blah tmp2;
tmp2.foo();

输出:

是参考:0是const:0是易失性的:0是引用:1是const:0是易失性的:0是参考的:1是const:1是易失性的:0是易失性的:0是易失性的:0是易失性的:0是易失性的:0是易失性的。 实例化

使用宏实现转发给朋友的方法,并手动编写朋友。转发给朋友的方法甚至可以是template<class...Args>,如果您对完美转发的缺点感到满意的话。

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

代码语言:javascript
复制
#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缩短为:

代码语言:javascript
复制
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()现在用适当的CV和L/R值条件来调用do_foo( some_blah ),除了在some_blah上没有。

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

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47140281

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档