繁体   English   中英

继承 std::array 和聚合初始化

[英]Inherited std::array and aggregate initialization

我需要比较使用不同过程计算的双精度三元组,这些过程导致它们存在少量差异,但应被视为等效。 一种似乎有效的方法是以这样一种方式继承std::array ,即可以在彼此的某个增量内比较这些值。 这似乎有效:

template <int precision_equals = 4> // default equal test precision is .1^4 (.0001)
class RGB : public std::array<double,3>

我还需要与需要转换构造函数的标准 arrays 互操作。 但是,当提供构造函数时,聚合初始化似乎是不允许的: 聚合初始化

没有用户提供的、继承的或显式的构造函数(允许显式默认或删除的构造函数)

但是我已经添加了这个构造函数,当从像b2 = a;这样的常规数组分配时需要它。 在代码中:

    RGB(const std::array<double,3>& x) {*static_cast<std::array<double,3>*>(this) = x;}

然而,这似乎有效。

RGB<2> b2{{ 1,2,3 }};

这不是聚合初始化吗? 我错过了什么吗?

#include <iostream>
#include <array>
#include <algorithm>
#include <vector>
using std::vector;
using std::array;
using std::cout;

template <int precision_equals = 4> // default equal test precision is .1^4 (.0001)
class RGB : public std::array<double,3>
{
public:
    RGB(const std::array<double,3>& x) {*static_cast<std::array<double,3>*>(this) = x;}
    friend bool operator==(const RGB& a, const RGB& b)
    {
        auto resolution = [](int prec)
        {
            double factor = 1.0;
            while (prec--)
                factor = factor / 10.0;
            return factor;
        };
        constexpr double delta = resolution(precision_equals);
        return a[0] < b[0] + delta && a[0] > b[0] - delta
            && a[1] < b[1] + delta && a[1] > b[1] - delta
            && a[2] < b[2] + delta && a[2] > b[2] - delta;
    }
    friend bool operator!=(const RGB& a, const RGB& b) { return !(a == b); }
};


int main()
{
    // shows vector of inherited arrays can be sorted
    vector<RGB<2>> v{ {{1,2.0001,3}}, {{1,2,3}} };
    sort(v.begin(), v.end());

    array<double, 3> a{ 1,2,3 };

    RGB<2> b2{{ 1,2,3 }};
    RGB<2> c2{{ 1.001,2,3 }};
    RGB<3> b3{{ 1,2,3 }};
    RGB<3> c3{{ 1.005,2,3 }};

    // comparisons work
    cout << "b2==c2: " << (b2 == c2 ? "true\n" : "false\n");
    cout << "b3==c3: " << (b3 == c3 ? "true\n" : "false\n");

    // assignments to/from regular arrays work
    a = b2;
    b2 = a;
}

适用于 MSVC 和 GCC。链接到编译器资源管理器

@LanguageLawyer 指出赋值转换运算符将消除对转换构造函数的大部分需求。 删除转换构造函数并以此替换

    RGB& operator=(const std::array<double, 3>& from)
    {
        //return *this = *static_cast<const RGB*>(&from);  // UB

        (*this)[0] = from[0]; // ugly version that's not UB
        (*this)[1] = from[1];
        (*this)[2] = from[2];
        return *this;
    }

允许代码编译,这样我的用例就解决了。 但是,转换构造函数是否禁止聚合初始化的问题仍然存在。

调用基础构造函数应该更好

未经测试的代码

    RGB(const std::array<double,3>& x) : std::array<double, 3>(x) {}

或者稍微重写


using BaseRGB = std::array<double,3>;
template <int precision_equals = 4> // default equal test precision is .1^4 (.0001)
class RGB : public BaseRGB {
public:
    RGB(const BaseRGB& x) : BaseRGB(x) {}

    // or even
    using BaseRGB::BaseRGB; // using the constructor directly if you don't set up anything more.


暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM