有没有办法检测当前成员函数是在左值还是右值上运行?

时间:2019-04-28 16:07:59

标签: c++ c++17

限定符是一种基于对象上下文重载函数的好方法。这样的限定词是constvolatile。但是,为它们编写代码很烦人,因为它们通常是代码的重复,因为cv限定词至少由this传播。这样,我们可以使用传播技巧并借助autodecltype(auto)使整个函数(无cv限定词)完全相同。

例如:

struct X {
  int m_i = 0;

  auto& i()                &  { return m_i ; } // returns int                &
  auto& i()       volatile &  { return m_i ; } // returns int       volatile &
  auto& i() const          &  { return m_i ; } // returns int const          &
  auto& i() const volatile &  { return m_i ; } // returns int const volatile &
};

尽管很烦人,但至少我们可以看到,这将在使用相同代码的所有上下文中都有效,从而将错误降到最低。

但是,有了可以用于指定成员函数的新的左值/右值限定符,this不会传播该函数是在左值还是右值的对象上调用的。如果说我想这样做的话,这导致必须对功能进行些微改动:

struct X {
  int m_i = 0;

  auto&& i()                &  { return           m_i ; } // returns int                &
  auto&& i()       volatile &  { return           m_i ; } // returns int       volatile &
  auto&& i() const          &  { return           m_i ; } // returns int const          &
  auto&& i() const volatile &  { return           m_i ; } // returns int const volatile &

  auto&& i()                && { return std::move(m_i); } // returns int                &&
  auto&& i()       volatile && { return std::move(m_i); } // returns int       volatile &&
  auto&& i() const          && { return std::move(m_i); } // returns int const          &&
  auto&& i() const volatile && { return std::move(m_i); } // returns int const volatile &&
};

能够使它们全部相同将是很好的。

类似这样的东西:

struct X {
  int m_i = 0;

  decltype(auto) i()                &  { return std::forward<...some_magic...>(m_i); } // returns int                &
  decltype(auto) i()       volatile &  { return std::forward<...some_magic...>(m_i); } // returns int       volatile &
  decltype(auto) i() const          &  { return std::forward<...some_magic...>(m_i); } // returns int const          &
  decltype(auto) i() const volatile &  { return std::forward<...some_magic...>(m_i); } // returns int const volatile &

  decltype(auto) i()                && { return std::forward<...some_magic...>(m_i); } // returns int                &&
  decltype(auto) i()       volatile && { return std::forward<...some_magic...>(m_i); } // returns int       volatile &&
  decltype(auto) i() const          && { return std::forward<...some_magic...>(m_i); } // returns int const          &&
  decltype(auto) i() const volatile && { return std::forward<...some_magic...>(m_i); } // returns int const volatile &&
};

如果当前成员函数是在左值还是右值上运行,是否有任何方法可以查询?

1 个答案:

答案 0 :(得分:7)

不,没有。

在成员函数主体的范围内,您自己具有的唯一访问权是:thisthis始终是X [cv]* const,而*this始终是左值-X [cv]&。它可以告诉您成员函数的 cv 限定词是什么,但不能告诉您该函数的 ref 限定词是什么。

您将必须将所有成员函数间接转换为非成员函数,并以左值或右值形式适当地传递自己:

decltype(auto) i() &  { return free_i(*this); }
decltype(auto) i() && { return free_i(std::move(*this)); }

template <typename Self>
friend decltype(auto) free_i(Self&& self) { ... }

P0847也可以解决此问题,但是在C ++ 20中也不会。也许是C ++ 23:

template <typename Self>
decltype(auto) i(this Self&& self) { ... }

在这里,您可以直接获得self是什么类型的引用。