限定符是一种基于对象上下文重载函数的好方法。这样的限定词是const
和volatile
。但是,为它们编写代码很烦人,因为它们通常是代码的重复,因为cv限定词至少由this
传播。这样,我们可以使用传播技巧并借助auto
或decltype(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 &&
};
如果当前成员函数是在左值还是右值上运行,是否有任何方法可以查询?
答案 0 :(得分:7)
不,没有。
在成员函数主体的范围内,您自己具有的唯一访问权是:this
。 this
始终是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
是什么类型的引用。