为什么自定义数据的 thrust::sort 需要一个默认的构造器,而 STL::sort 不需要?

Why does thrust::sort for customized data needs a default constuctor while STL::sort does't?

本文关键字:sort 构造器 默认 一个 STL 不需要 thrust 数据 自定义 为什么      更新时间:2023-10-16

我正在尝试使用推力按最小x坐标对一组三角形进行排序:

struct real3 
{
    float x, y, z;
};
struct triangle
{
    real3 p1, p2, p3;
    float Xmin, Xmax;
    triangle(real3 ip1, real3 ip2, real3 ip3) :p1(ip1), p2(ip2), p3(ip3)
    {
        Xmax = (p1.x > p2.x) ? ((p1.x > p3.x) ? p1.x : p3.x) : ((p2.x > p3.x) ? p2.x : p3.x);
        Xmin = (p1.x < p2.x) ? ((p1.x < p3.x) ? p1.x : p3.x) : ((p2.x < p3.x) ? p2.x : p3.x);
    }
};
bool triangle_less_Xmin(const triangle& f, const triangle& b)
{
    return f.Xmin < b.Xmin;
}

thrust::device_vector<triangle> devXXX(XXX);
thrust::sort(devXXX.begin(), devXXX.end(), triangle_less_Xmin);

但在编译时,一条错误消息抱怨说"类Stringle不存在默认构造函数"。但如果我使用std::vector进行如下排序:

std::vector<triangle> sss;
std::sort(sss.begin(), sss.end(), triangle_less_Xmin);

一切顺利。此外,如果我将triangle(){}添加到结构中,推力也会编译得很好。那么,问题出在哪里呢?据我所知,排序并不需要创建新的数据。我应该在默认构造函数中做一些特别的事情吗?


30分钟后编辑

我在推力源代码中发现了这一点,但并不知道确切的含义。这就是错误指向的地方:

__host__ inline static result_type host_path(execution_policy<DerivedPolicy> &exec, Pointer ptr)
{
  // when called from host code, implement with assign_value
  // note that this requires a type with default constructor
  result_type result;
  thrust::host_system_tag host_tag;
  cross_system<thrust::host_system_tag, DerivedPolicy> systems(host_tag, exec);
  assign_value(systems, &result, ptr);
  return result;
}

您的问题中已经有了错误的来源和解决方案,编译器提供了一条信息丰富的错误消息。

但为了完整性,Thrust要求triangle类有一个默认的构造函数,尽管我不确定你发布的代码在代码库中的确切位置(或者你的devXXX实际上是一个主机向量,而不是设备向量),但Thrust在某个地方没有参数地实例化你的类,导致了你看到的失败。

通常,当使用显式非默认构造函数定义类时,还应该提供自己的默认构造函数,因为提供任何构造函数定义都会禁用编译器的隐式默认构造函数。

所以这是可以的:

struct triangle
{
    real3 p1, p2, p3;
    float Xmin, Xmax;
};
triangle t;  // Implicit default constructor called

这是正常的

struct triangle
{
    real3 p1, p2, p3;
    float Xmin, Xmax;
    triangle() {};
    triangle(real3 ip1, real3 ip2, real3 ip3) :p1(ip1), p2(ip2), p3(ip3)
    {
        Xmax = (p1.x > p2.x) ? ((p1.x > p3.x) ? p1.x : p3.x) : ((p2.x > p3.x) ? p2.x : p3.x);
        Xmin = (p1.x < p2.x) ? ((p1.x < p3.x) ? p1.x : p3.x) : ((p2.x < p3.x) ? p2.x : p3.x);
    }
};
triangle  t; // Explicit default constructor called 

但是你的定义

struct triangle
{
    real3 p1, p2, p3;
    float Xmin, Xmax;
    triangle(real3 ip1, real3 ip2, real3 ip3) :p1(ip1), p2(ip2), p3(ip3)
    {
        Xmax = (p1.x > p2.x) ? ((p1.x > p3.x) ? p1.x : p3.x) : ((p2.x > p3.x) ? p2.x : p3.x);
        Xmin = (p1.x < p2.x) ? ((p1.x < p3.x) ? p1.x : p3.x) : ((p2.x < p3.x) ? p2.x : p3.x);
    }
};
triangle t; // Syntax error here, no default constructor

不正常,因为您在没有提供自己的构造函数的情况下重写了编译器的默认构造函数。您应该将类使用std::sort这一事实视为意外,而不是Thrust中的任何缺陷。