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

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

我正在尝试使用推力按最小 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);

但在编译时,一条错误消息抱怨 "no default constructor exists for class tringle"。但是如果我使用 std::vector 进行如下排序:

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

一切顺利。另外,如果我将 triangle(){} 添加到结构中,thrust 编译也很好。 那么,问题是什么?据我所知,排序不需要创建新数据。我应该在默认构造函数中做一些特殊的事情吗?


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 class 具有默认构造函数,尽管我不确定您发布的代码是否准确指出了代码库中的确切位置(或者你的 devXXX 实际上是一个主机向量而不是设备向量),某处推力正在实例化你的 class 没有参数,导致你看到的失败。

一般来说,当用显式非默认构造函数定义 class 时,您还应该提供自己的默认构造函数,因为提供 any 构造函数定义会禁用编译器的隐式默认构造函数。

这样就可以了:

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

不正常,因为您在没有提供自己的构造函数的情况下覆盖了编译器的默认构造函数。您应该将您的 class 与 std::sort 一起工作这一事实视为意外,而不是 Thrust 的任何缺陷。