C++ 如何确定类型是否为memcpy save?

C++ 如何确定类型是否为memcpy save?,c++,memcpy,typetraits,C++,Memcpy,Typetraits,我与非常喜欢memcpy的同事一起工作。我移植的代码通常处理简单类型(doubles),可以使用memcpy安全地复制这些类型,并将其扩展到非普通类型。我想编写一个简单的复制函数,根据所讨论的类型执行正确的操作: #include <string.h> #include <vector> #include <type_traits> template<class T> void fancy_copy(const T* src,

我与非常喜欢memcpy的同事一起工作。我移植的代码通常处理简单类型(
double
s),可以使用
memcpy
安全地复制这些类型,并将其扩展到非普通类型。我想编写一个简单的复制函数,根据所讨论的类型执行正确的操作:

#include <string.h>
#include <vector>
#include <type_traits>

template<class T>
void fancy_copy(const T* src,
                T* dest,
                unsigned int size)
{
  // here:
  if(std::is_trivially_copy_assignable<T>::value)
  {
    memcpy(dest, src, sizeof(T) * size);
  }
  else
  {
    for(unsigned int i = 0; i < size; ++i)
    {
      dest[i] = src[i];
    }
  }
}

class Custom
{
private:
  int value;
public:
  Custom& operator=(const Custom& other)
  {
    value = other.value + 1;
    return *this;
  }
};

int main()
{
  const unsigned int size = 10;

  {
    std::vector<int> source(size, 0);
    std::vector<int> target(size, 0);

    fancy_copy<int>(source.data(), target.data(), size);
  }

  {
    std::vector<Custom> source(size);
    std::vector<Custom> target(size);

    fancy_copy<Custom>(source.data(), target.data(), size);
  }

  return 0;
}


因此,对于我的
Custom
类,
memcpy
被错误地使用。我需要使用哪种类型特征来选择正确的操作并使警告静音?

用于此操作的正确类型特征是,而不是
std::is \u琐碎地\u复制\u可分配的

要修复警告,请使用而不是
if
在编译时执行检查,并仅生成两个分支中的一个作为给定类型
T
的无条件逻辑。即使由于运行时条件逻辑而无法访问格式错误的调用,编译器也会发出警告,因为该调用仍然存在于生成的代码中

也可考虑使用< <代码>

对于C++11,您可以使用来选择编译时要使用的实现,类似于C++17
if constexpr

模板
typename std::enable_if::type
花式复制(常量T*src、T*dest、无符号整数大小)
{
memcpy(目的地、src、尺寸(T)*尺寸);
}
模板
typename std::enable_if::value>::type
花式复制(常量T*src、T*dest、无符号整数大小)
{
标准:副本(src、大小、目的地);
}
请在godbolt.org上试用:


不过,正如其他人所指出的,这种
fancy\u copy
可能是一种过早的优化,您最好在语义正确的地方使用
std::copy\n
,允许编译器执行自己的优化。使用
-O3
时,比较和之间的二进制文件,以便自己查看。它们完全相同。

用于此的正确类型特征是,而不是
std::is\u琐碎地\u copy\u assignable

要修复警告,请使用而不是
if
在编译时执行检查,并仅生成两个分支中的一个作为给定类型
T
的无条件逻辑。即使由于运行时条件逻辑而无法访问格式错误的调用,编译器也会发出警告,因为该调用仍然存在于生成的代码中

也可考虑使用< <代码>

对于C++11,您可以使用来选择编译时要使用的实现,类似于C++17
if constexpr

模板
typename std::enable_if::type
花式复制(常量T*src、T*dest、无符号整数大小)
{
memcpy(目的地、src、尺寸(T)*尺寸);
}
模板
typename std::enable_if::value>::type
花式复制(常量T*src、T*dest、无符号整数大小)
{
标准:副本(src、大小、目的地);
}
请在godbolt.org上试用:


不过,正如其他人所指出的,这种
fancy\u copy
可能是一种过早的优化,您最好在语义正确的地方使用
std::copy\n
,允许编译器执行自己的优化。使用
-O3
时,比较和之间的二进制文件,以便自己查看。它们完全相同。

。我认为您有这个错误,因为即使
是\u微不足道的\u copy\u assignable
是false,编译器仍然会看到
memcpy
代码。你试过用它来代替吗?告诉您它是否可以被memcopy“一个简单的复制函数,它做正确的事情”-我称之为
std::copy
。标准库实现者通常会非常好地优化这些常用算法。@freakish:No。正如StoryTeller正确指出的那样,
std::copy
实际上是默认副本。它适用于所有可复制类型,并且通常经过优化。它甚至可以击败
memcpy
,因为
memcpy
也必须支持未对齐的副本。但是
double
double
是对齐的。我认为您有这个错误,因为即使
是可分配的
是false,编译器仍然会看到
memcpy
代码。你试过用它来代替吗?告诉您它是否可以被memcopy“一个简单的复制函数,它做正确的事情”-我称之为
std::copy
。标准库实现者通常会非常好地优化这些常用算法。@freakish:No。正如StoryTeller正确指出的那样,
std::copy
实际上是默认副本。它适用于所有可复制类型,并且通常经过优化。它甚至可以击败
memcpy
,因为
memcpy
也必须支持未对齐的副本。但是
double
double
是对齐的。我甚至不知道
constepr if
。对于C++17之前的版本,有什么方法可以达到同样的效果吗?@hfhc2您使用的是C++11还是14?好吧,恐怕我已经听命于C++11了是的
std::copy\u n
非常快,有时比
memcpy
更快,当编译器可以计算对齐时,这可能是一个优势。在C++代码中仍然使用MeMCPY只是货物崇拜编程,我甚至不知道<>代码> CONTXPR,如果。对于C++17之前的版本,有什么方法可以达到同样的效果吗?@hfhc2您使用的是C++11还是14?好吧,恐怕我已经听命于C++11了是的
std::copy\u n
非常快,有时比
memcpy
更快,当编译器可以计算对齐时,这可能是一个优势。在C++代码中仍然使用MeMCPY只是货物崇拜编程。
warning: ‘void* memcpy(void*, const void*, size_t)’ writing to an object of type ‘class Custom’ with no trivial copy-assignment; use copy-assignment or copy-initialization instead [-Wclass-memaccess]