此问题已更新。请查看代码。
以下代码是使用VC ++ 2012年11月的CTP编译的。斯科特迈耶斯'本书" 有效的C ++ "建议我们应该使用方法来避免const和非const成员函数的重复。但是,以下代码会导致警告(级别1)。因为WDK构建工具将警告视为错误,所以无法成功编译以下代码。
还有其他更好的方法吗?
struct A
{
int n;
A(int n)
: n(n)
{}
int Get() const
{
return n;
}
int Get()
{
return static_cast<const decltype(*this)&>(*this).Get();
}
};
int main()
{
const A a(8);
//
// warning C4717: 'A::Get' : recursive on all control paths,
// function will cause runtime stack overflow
//
a.Get();
}
答案 0 :(得分:6)
您已经转换了两个Get
方法的主体,因此编译器是正确的; const Get
方法调用自身。现在您的构建工具将警告视为错误,您不高兴吗? :)
交换它们:
int& Get()
{
return const_cast<int&>(static_cast<const A&>(*this).Get());
}
const int& Get() const
{
return n;
}
答案 1 :(得分:4)
我相信你反过来了。这是非const版本,它会在const版本上抛弃const。
请参阅:Elegant solution to duplicate, const and non-const, getters?
答案 2 :(得分:1)
回答更新后的问题。 (你应该把它作为一个新问题)
在static_cast<const decltype(*this)&>(*this)
中,*this
是A
类型的左值,因此decltype(*this)
表示的类型为A&
(见7.1.6.2 [dcl。 type.simple] / 4)。
因此,非const Get()
函数等同于:
int Get()
{
typedef A & Aref;
// IMHO a const_cast would be the better choice here
return static_cast<const Aref&>(*this).Get();
}
忽略引用类型上的 cv-qualifiers 。使用引用折叠,您的强制转换最终与static_cast<A&>(*this)
等效,因此您不需要添加所需的const。
所以使用decl_type
在这里不起作用。如果你非常想要使用它,你需要:
int Get()
{
// Made my suggested change of cast here
return const_cast<const std::remove_reference<decltype(*this)>::type&>(*this).Get();
}