繁体   English   中英

自动转换结构的所有成员

[英]Casting all members of struct automatically

我有一个模板 class 有很多变量,都是相同的类型

template<typename T>
struct Location
{
    T lat;
    T lon;
    T alt;
    // and roughly 20 variables more of type T
};

在我的代码中, Tfloatdouble ,具体取决于我需要的精度。 有时我需要在这两个结构之间进行转换。 因此我想定义一个转换运算符

template<typename A, typename B> operator Location<B> {
    Location<B> ret;
    // cast every variable in *this from type A to type B
    return ret;
}

由于Location中有很多变量,并且将来我很可能需要向结构添加更多变量,所以我不想在我的转换运算符中手动编写每个转换。

因此,我想知道是否有某种自动方式来转换结构中的所有变量?

恐怕没有这种方法。 我可能会编写模板复制构造函数并手动分配每个变量。 你现在只做一次,然后每次添加一个新变量 - 这不是什么大问题 IMO。

你不能在本地做到这一点。

您可以编写的一个 function 可能在其他上下文(例如比较)中有用的是tie / as_tuple方法:

template<typename T>
struct Location
{
    T lat;
    T lon;
    T alt;
    // and roughly 20 variables more of type T

    auto as_tuple() const { return std::tie(lat, lon, alt /*, ..*/); }

    template <typename T2> operator Location<T2>() const
    {
        return std::make_from_tuple<Location<T2>>(as_tuple());
        // return std::apply([](auto... args){ return Location<T2>{static_cast<T2>(args)...}; },
        //                   as_tuple());
    }
};

就我个人而言,我从来没有这个用例,但是如果该结构中的所有条目都是相同类型的,那么不应该像下面这样工作吗?

template<typename T>
struct Location {
    T a;
    T b;
    T c;

    template<typename B> operator Location<B>() {
        if constexpr(std::is_same_v<T,B>) {
            return *this;
        }
        Location<B> ret;

        constexpr std::size_t count = sizeof(Location<T>)/sizeof(T);
        static_assert(sizeof(Location<B>)==sizeof(B)*count);
        for (std::size_t i=0;i<count;++i){
            B b;
            T a;
            memcpy(&a, ((char*)this)+i*sizeof(T), sizeof(T));
            b = static_cast<B>(a);
            memcpy(((char*)&ret) + i*sizeof(B), &b, sizeof(B));
        }
        return ret;
    }
};

我很确定那个怪物的某个地方是UB,或者至少是memory alignment的问题。

这显然不适用于包含指针的指针或类型/结构。

没有好的方法可以做到这一点......但是这是一种完全可怕的方法,永远不应该使用并且仅在Location仅包含T实例时才有效。 也可能存在alignment 问题

template<typename B>
operator Location<B>() const {
    Location<B> ret;
    for (int i = 0; i <= (sizeof(Location<T>) / sizeof(T)); i++) {
        *(&ret.lat + i) = B(*(&lat + i));
    }
    return ret;
}

暂无
暂无

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

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