为了真正地将调用转发到成员函数,我们必须考虑正确转发成员调用的
*this
值的必要性。
下面是示例:
template<typename Type>
struct Fwd {
Type member;
template<typename ...Args>
decltype(auto) Func(Args&&... args)
noexcept(noexcept(member.Func(std::forward<Args>(args)...)))
{ return member.Func(std::forward<Args>(args)...); }
};
正如你可能猜到的那样,它足以转发参数和异常规范。 但是,它不足以完美转发*this
:
struct S {
void Func(int) & {}
void Func(int&&) & {}
void Func(int) const&;
void Func(int&&) const&;
void Func(int) volatile&;
void Func(int&&) volatile&;
void Func(int) const volatile&;
void Func(int&&) const volatile&;
void Func(int) &&;
void Func(int&&) &&;
void Func(int) const&&;
void Func(int&&) const&&;
void Func(int) volatile&&;
void Func(int&&) volatile&&;
void Func(int) const volatile&&;
void Func(int&&) const volatile&&;
};
针对这个问题,有两种解决方案。第一种是手动创建所有可能的重载函数,如果需要的话可以使用宏来简化操作:
#define FWD(member, Func) \
template<typename ...Args> \
decltype(auto) Func(Args&&... args) & \
noexcept(noexcept(member.Func(std::forward<Args>(args)...))) \
{ return member.Func(std::forward<Args>(args)...); } \
\
template<typename ...Args> \
decltype(auto) Func(Args&&... args) const& \
noexcept(noexcept(member.Func(std::forward<Args>(args)...))) \
{ return member.Func(std::forward<Args>(args)...); } \
\
template<typename ...Args> \
decltype(auto) Func(Args&&... args) volatile& \
noexcept(noexcept(member.Func(std::forward<Args>(args)...))) \
{ return member.Func(std::forward<Args>(args)...); } \
\
template<typename ...Args> \
decltype(auto) Func(Args&&... args) const volatile& \
noexcept(noexcept(member.Func(std::forward<Args>(args)...))) \
{ return member.Func(std::forward<Args>(args)...); } \
\
template<typename ...Args> \
decltype(auto) Func(Args&&... args) && \
noexcept(noexcept(member.Func(std::forward<Args>(args)...))) \
{ return std::move(member).Func(std::forward<Args>(args)...); } \
\
template<typename ...Args> \
decltype(auto) Func(Args&&... args) const&& \
noexcept(noexcept(member.Func(std::forward<Args>(args)...))) \
{ return std::move(member).Func(std::forward<Args>(args)...); } \
\
template<typename ...Args> \
decltype(auto) Func(Args&&... args) volatile&& \
noexcept(noexcept(member.Func(std::forward<Args>(args)...))) \
{ return std::move(member).Func(std::forward<Args>(args)...); } \
\
template<typename ...Args> \
decltype(auto) Func(Args&&... args) const volatile&& \
noexcept(noexcept(member.Func(std::forward<Args>(args)...))) \
{ return std::move(member).Func(std::forward<Args>(args)...); }
template<typename Type>
struct Fwd {
Type member;
FWD(member, Func)
};
另一种解决方案是完全避免使用成员函数,而是使用自由函数:
template<typename Fwd, typename ...Args>
decltype(auto) Func(Fwd&& fwd, Args&&... args)
noexcept(noexcept(std::forward<Fwd>(fwd).Func(std::forward<Args>(args)...))) {
return std::forward<Fwd>(fwd).Func(std::forward<Args>(args)...);
}
insert
包装器的返回类型吗?decltype(auto)
。 - dypsomething
应包含正确的 cv 和 ref 限定符以及异常说明吗? - dyp