kor*_*n00 0 gcc decltype c++11 visual-studio-2013
在尝试制定C宏以简化非const成员函数的编写时,使用完全相同的逻辑调用const成员函数(参见第1章,第3项,"在有效C++中避免const和非const成员函数中的重复" ),我相信我decltype()
在VS2013 Update 1中遇到了一个错误.
我想用来在前面提到的宏中decltype(*this)
构建一个static_cast<decltype(*this) const&>(*this)
表达式,以避免宏调用站点传递任何显式类型信息.但是,在VS2013的某些情况下,后一个表达式似乎没有正确地添加const.
这是一小块代码,我能够回复这个bug:
#include <stdio.h>
template<typename DatumT>
struct DynamicArray
{
DatumT* elements;
unsigned element_size;
int count;
inline const DatumT* operator [](int index) const
{
if (index < 0 || index >= count)
return nullptr;
return &elements[index];
}
inline DatumT* operator [](int index)
{
#if defined(MAKE_THIS_CODE_WORK)
DynamicArray const& _this = static_cast<decltype(*this) const&>(*this);
return const_cast<DatumT*>(_this[index]);
#else
// warning C4717: 'DynamicArray<int>::operator[]' : recursive on all control paths, function will cause runtime stack overflow
return const_cast<DatumT*>(
static_cast<decltype(*this) const>(*this)
[index]
);
#endif
}
};
int _tmain(int argc, _TCHAR* argv[])
{
DynamicArray<int> array = { new int[5], sizeof(int), 5 };
printf_s("%d", *array[0]);
delete array.elements;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
(可能第一个关于不使用std :: vector的人应该被重击)
您可以编译上面的代码并自己查看警告,或者参考我的单独评论来查看VC++会向您发出的内容.那你可以!defined(MAKE_THIS_CODE_WORK)
VC++编译代码的表达式,除了#else
代码工作之外.
我没有在这台机器上设置我可靠的clang,但是我能够使用GCC Explorer查看clang是否抱怨(点击查看/编译代码).它没有.但是,g ++ 4.8将‘const’ qualifiers cannot be applied to ‘DynamicArray&’
使用相同的代码给您一条错误消息.那么也许g ++也有bug?
参考decltype和auto标准论文(尽管它已经差不多11年了),第6页的最底层说decltype(*this)
在非const成员函数中应该是T&
,所以我很确定这应该是合法的......
所以我错误地尝试在*上使用decltype()加上向它添加const?或者这是VS2013中的错误?显然是g ++ 4.8,但是以不同的方式.
编辑:感谢Ben Voigt的回复,我能够弄清楚如何为我想做的事情制作一个独立的C宏.
// Cast [this] to a 'const this&' so that a const member function can be invoked
// [ret_type] is the return type of the member function. Usually there's a const return type, so we need to cast it to non-const too.
// [...] the code that represents the member function (or operator) call
#define CAST_THIS_NONCONST_MEMBER_FUNC(ret_type, ...) \
const_cast<ret_type>( \
static_cast< \
std::add_reference< \
std::add_const< \
std::remove_reference< \
decltype(*this) \
>::type \
>::type \
>::type \
>(*this) \
__VA_ARGS__ \
)
// We can now implement that operator[] like so:
return CAST_THIS_NONCONST_MEMBER_FUNC(DatumT*, [index]);
Run Code Online (Sandbox Code Playgroud)
最初的愿望是将这一切隐藏在一个宏中,这就是为什么我不想担心创建typedef或this
别名.仍然很奇怪GCC Explorer中的clang没有输出警告......尽管输出组件确实显得很腥.
你说自己,decltype (*this)
是T&
. decltype (*this) const &
尝试形成对引用(T& const &
)的引用. decltype
触发参考折叠规则8.3.2p6.但它并没有像你想的那样崩溃.
你可以说decltype(this) const&
,但那是T* const&
- 对const指针的引用,而不是指向const对象的指针.出于同样的原因,decltype (*this) const
并const decltype (*this)
没有形成const T&
,但是(T&) const
.并且const
引用上的顶级是无用的,因为引用已经禁止重新绑定.
也许你正在寻找更像的东西
const typename remove_reference<decltype(*this)>::type &
Run Code Online (Sandbox Code Playgroud)
但请注意,添加时根本不需要演员表const
.代替
DynamicArray const& _this = static_cast<decltype(*this) const&>(*this);
Run Code Online (Sandbox Code Playgroud)
说啊
DynamicArray const& _this = *this;
Run Code Online (Sandbox Code Playgroud)
这些结合起来
const typename std::remove_reference<decltype(*this)>::type & this_ = *this;
Run Code Online (Sandbox Code Playgroud)
尽管如此,对于一个非常简单和普遍存在的问题,这是一个愚蠢的代码量.说啊:
const auto& this_ = *this;
仅供参考,这是参考折叠规则的文本:
如果typedef-name(7.1.3,14.1)或decltype-specifier(7.1.6.2)表示作为类型
TR
引用的类型T
,则尝试创建类型"lvue reference to cvTR
"会创建类型"lvalue"引用T
",而尝试创建类型"对cv的 rvalue引用TR
"创建类型TR
.
decltype(*this)
是我们的decltype-specifier表示TR
,即DynamicArray<DatumT>&
.在这里,T
是DynamicArray<DatumT>
.尝试TR const&
是第一种情况,尝试创建(const)的左值引用TR
,因此最终结果T&
不是const T&
.cv资格不在最内层参考之内.
归档时间: |
|
查看次数: |
186 次 |
最近记录: |