【发布时间】:2014-04-17 19:58:58
【问题描述】:
在尝试制定 C 宏以简化非常量成员函数的编写时,调用具有完全相同逻辑的 const 成员函数(参见 @ 987654321@),我相信我在 VS2013 Update 1 中遇到了 decltype() 错误。
我想使用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;
}
(可能第一个喋喋不休地谈论不使用 std::vector 的人)
您可以编译上面的代码并自己查看警告,或者参考我的唯一评论以了解 VC++ 会向您吐出什么。那你就可以了! defined(MAKE_THIS_CODE_WORK) 表达式让 VC++ 编译代码,就像我除了 #else 代码一样工作。
我在这台机器上没有可靠的 clang 设置,但我可以使用 GCC Explorer 查看 clang 是否抱怨 (click to see/compile code)。它没有。但是,g++ 4.8 会使用相同的代码为您提供‘const’ qualifiers cannot be applied to ‘DynamicArray&’ 错误消息。那么也许g++也有bug?
参考decltype and auto 标准文件(尽管它已经快 11 年了),第 6 页的最底部说非 const 成员函数中的decltype(*this) 应该是T&,所以我很漂亮当然这应该是合法的......
那么我尝试在 *this 上使用 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]);
最初的愿望是将这一切隐藏在一个宏中,这就是为什么我不想担心创建 typedef 或 this 别名的原因。令人好奇的是 GCC Explorer 中的 clang 没有输出警告……尽管输出程序集确实看起来很可疑。
【问题讨论】:
-
我想我的问题可以被认为是这个问题的重复(尽管我在研究我最初的问题时没有遇到它)stackoverflow.com/questions/7416251/…
标签: gcc c++11 visual-studio-2013 decltype