自动转换结构的所有成员
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
};
在我的代码中,T
是 float
或 double
,具体取决于我需要的精度。有时我需要在这两个结构之间进行转换。因此我想定义一个转换运算符
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 没什么大不了的。
就我个人而言,我从未有过这个用例,但如果该结构中的所有条目都属于同一类型,不应该像下面这样工作吗?
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 或者至少是内存对齐问题。
这显然不适用于指针或包含指针的 types/structs。
没有好的方法来做到这一点...但这里有一个完全糟糕的方法,永远不要使用它,并且只有在 Location
只包含 T
个实例时才有效。也可能有alignment issues.
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;
}
你无法在本地执行此操作。
您可以编写的一个函数可能在其他上下文(例如比较)中有用,它是 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());
}
};
我有一个模板class,其中有很多变量,都是同一类型
template<typename T>
struct Location
{
T lat;
T lon;
T alt;
// and roughly 20 variables more of type T
};
在我的代码中,T
是 float
或 double
,具体取决于我需要的精度。有时我需要在这两个结构之间进行转换。因此我想定义一个转换运算符
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 没什么大不了的。
就我个人而言,我从未有过这个用例,但如果该结构中的所有条目都属于同一类型,不应该像下面这样工作吗?
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 或者至少是内存对齐问题。
这显然不适用于指针或包含指针的 types/structs。
没有好的方法来做到这一点...但这里有一个完全糟糕的方法,永远不要使用它,并且只有在 Location
只包含 T
个实例时才有效。也可能有alignment issues.
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;
}
你无法在本地执行此操作。
您可以编写的一个函数可能在其他上下文(例如比较)中有用,它是 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());
}
};