前言: 嘿,假设我有各种数据的表示方式,并且希望以任意方式轻松地在它们之间进行转换。这些表示是我无法控制的。我的一个实际例子是 3D 中的对象定向:我们有四元数、欧拉角、角轴和旋转矩阵,都来自不同库的各种类(我必须使用)。为此,我建立了一个代理类,它将值存储在一种特定的表示中,并可以通过重载的构造函数将其转换到该表示形式并通过重载的类型转换运算符将其转出,就像这样:
Eigen::Quaterniond eig_quaternion = AttitudeConvertor(roll, pitch, yaw);
tf2::Quaternion tf2_quaternion = AttitudeConvertor(eig_quaternion);
问题:到目前为止,一切都很好,直到我想要重载std::tuple的类型转换函数,这在返回yaw、pitch和roll角度时非常方便,代码如下:auto [roll2, pitch2, yaw2] = AttitudeConvertor(tf2_quaternion);
该类可以编译,但对于`auto [a, b, c]`和`std::tie(a,b,c)`的赋值不能正常工作。解决方法可以通过创建一个专用函数来返回元组或者创建一个自定义类来存储三个double。这些方法都可以正常工作,但不够流畅。我知道函数不能以其返回类型进行重载,这就是我创建代理类的原因。但是,是否有其他方法可以返回元组呢?即使只是针对元组的一个变体?还是我应该用不同的方式来解决这个问题?
我准备了一个最小(非)工作示例,主题为更简单的数字转换:
#include <iostream>
#include <math.h>
#include <tuple>
using namespace std;
class NumberConvertor {
public:
// | ---------------------- constructors ---------------------- |
NumberConvertor(const int& in) {
value_ = double(in);
}
NumberConvertor(const double& in) : value_(in){};
// | ------------------- typecast operators ------------------- |
operator int() const {
return int(value_);
}
operator double() const {
return value_;
}
// return the integer and the fractional part
operator std::tuple<int, double>() const {
int int_part = floor(value_);
double frac_part = fmod(value_, int_part);
return std::tuple(int_part, frac_part);
}
// | ------------------------ functions ----------------------- |
// the workaround
std::tuple<int, double> getIntFrac(void) const {
int int_part = floor(value_);
double frac_part = fmod(value_, int_part);
return std::tuple(int_part, frac_part);
}
private:
double value_; // the internally stored value in the 'universal representation'
};
int main(int argc, char** argv) {
// this works just fine
int intval = NumberConvertor(3.14);
double fracval = NumberConvertor(intval);
cout << "intval: " << intval << ", fracval: " << fracval << endl;
// this does not compile
// auto [int_part, frac_part] = NumberConvertor(3.14);
// neither does this
// int a;
// double b;
// std::tie(a, b) = NumberConvertor(3.14);
// the workaround
auto [int_part2, frac_part2] = NumberConvertor(3.14).getIntFrac();
cout << "decimal and fractional parts: " << int_part2 << ", " << frac_part2 << endl;
std::tie(int_part2, frac_part2) = NumberConvertor(1.618).getIntFrac();
cout << "decimal and fractional parts: " << int_part2 << ", " << frac_part2 << endl;
return 0;
};
Makefile:
main: main.cpp
g++ -std=c++17 main.cpp -o main
all: main
预期输出:
intval: 3, fracval: 3
decimal and fractional parts: 3, 0.14
decimal and fractional parts: 1, 0.618
binding_a_tuple-like_type
可能会有所帮助。 - Jarod42