因为我想重载一个成员函数的所有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; }
Run Code Online (Sandbox Code Playgroud)
不幸的是,如果我想以*this
转发方式返回(即this
在返回类型中保留-pointer的所有引用和cv限定,似乎,我必须手动编写所有这8个重载.
现在我的问题是:是否有可能以*this
通用方式获得cv和引用限定类型?
我试过decltype(auto)
作为返回类型和
return std::forward<decltype(*this)>(*this);
Run Code Online (Sandbox Code Playgroud)
但显然,即使在&&
合格函数的情况下,结果表达式也总是解析为左值引用.
你能帮助我吗?
你需要的是一个朋友.
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);
}
};
Run Code Online (Sandbox Code Playgroud)
测试代码:
blah{}.foo();
blah tmp;
tmp.foo();
const blah tmp2;
tmp2.foo();
Run Code Online (Sandbox Code Playgroud)
输出:
Run Code Online (Sandbox Code Playgroud)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 )
Run Code Online (Sandbox Code Playgroud)
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
}
};
Run Code Online (Sandbox Code Playgroud)
替换(和改进)所有foo()
方法.
some_blah.foo()
现在调用do_foo( some_blah )
适当的CV和L/R值资格和noexcept some_blah
.
constexpr
可能需要一些爱才能做对,因为我们现在没有在C++中进行条件constexpr测试.也许只是constexpr
在foo
生成的模板中声称是正确的,但我对这个问题很朦胧.
归档时间: |
|
查看次数: |
372 次 |
最近记录: |