关于非纯旧数据上的memset的编译时警告
Compile time warning about memset on non plain old data
我正在处理一个大型代码库,将一些旧的C模块转换为C++。我想把一个C++对象添加到结构中,但这个结构的一些用户memset
它,这对我想放在结构中的对象来说是不幸的。
我如何在编译时检测到这一点,以便在这样一个不再是POD的结构上消除memset
的所有使用?
我不确定编译器是否会通过直接提供一些编译标志来帮助您。如果是,对你有好处。使用它。故事结束了。
如果没有,也许这会对你有所帮助。由于您正在将代码从C转换为C++,这意味着所有对memset的使用都没有std::
命名空间。因此,利用这一事实和#define memset
作为:
#define memset memset_if_pod_else_error()
这里memset_if_pod_else_error
是您编写的函数(即您必须实现它)。您可以将其设置为模板,以便推断参数的类型,然后检测该类型是否为POD。如果是POD,那么这很好,并在内部调用std::memset
,否则会引发错误。
像std::enable_if
和std::is_pod
这样的元函数将帮助您实现此函数。
以下是这个想法的最小演示:
#include <iostream>
#include <type_traits>
#include <cstring>
auto ptr_memset = std::memset; //store this a pointer
template<typename T>
using VoidPtr = typename std::enable_if<std::is_pod<T>::value, void*>::type;
#define memset memset_if_pod_else_error
template<typename T>
VoidPtr<T> memset_if_pod_else_error(T *data, int ch, size_t count)
{
return ptr_memset(data, ch, count);
}
struct pod {};
struct nonpod { nonpod() {} };
int main()
{
pod p;
nonpod np;
memset(&p, 0, sizeof(p));
memset(&np, 0, sizeof(np)); //this is error!
}
对memset
的第二次调用生成以下错误:
错误:没有用于调用"memset_if_pod_else_error"的匹配函数
内存集(&np,0,sizeof(np))
^~~~~
在线演示。
希望能有所帮助。
这个怎么样:
auto orig_memset = std::memset;
#define memset checked_memset
template <class T>
void* checked_memset(T* ptr, int value, size_t num) {
static_assert(std::is_pod<T>::value, "memset on non-POD");
return original_memset(data, value, num);
}
或者,如果您只对查找特定结构的违规行为感兴趣:
auto original_memset = std::memset;
#define memset checked_memset
template <class T>
void* checked_memset(T* ptr, int value, size_t num) {
static_assert(!std::is_same<T, YOUR_STRUCT_HERE>::value, "memset used on YOUR_STRUCT_HERE");
return original_memset(data, value, num);
}
我认为您无法在编译时检测到在非POD数据上使用memset
。
您可以添加一个额外的字段,该字段在构造函数中设置,然后签入任何其他成员函数。类似这样的东西:
class X
{
const int MAGIC = 123456789;
int magic;
...
public:
X() : magic(MAGIC) { ... }
...
void do_stuff()
{
check_magic();
...
}
private:
void check_magic()
{
if (magic != MAGIC) { ... do something to indicate bad state ... };
}
};
显然,这可以"仅在调试构建时"完成。
在这种情况下,我建议不要试图找到所有的问题领域,而是从一开始就预防它们。具体来说,不要在现有的C结构中添加任何C++功能,而是使用包含C数据结构实例的适当接口编写类。然后,您可以保持与旧结构和代码的完全向后兼容性,并添加您感兴趣的新C++功能。