【问题标题】:Coping with different types with the same underlying data structure处理具有相同底层数据结构的不同类型
【发布时间】:2011-10-07 19:09:04
【问题描述】:

我需要在计算机模拟中混合 C 代码和 C++ 代码。

C 库具有引用常规双精度数组的函数:

void position(double[3])

另一个C库定义了自己的vector类型:

void do_something(*custom_vector)

而我的前端(C++)使用boost::numeric::ublas::vector

在第一种情况下,我有很多地方都有这种代码:

double tmp[3];
position(tmp)
boostvec r(3);
r(0) = tmp[0]; r(1) = tmp[1]; r(2) = tmp[2];
// continue working with r

还有

custom_vector *v;
do_something(v);
boostvec r(3);
r(0) = v[0]; r(1) = v[1]; r(2) = v[2];

在内部,所有类型最终都是矢量容器,但它们的细微实现差异导致大量样板爆炸。我也在处理很多不同版本的double(一些定义realtype(这是一个双精度),其他定义number(这是一个双精度)等)。

你如何处理这种情况?

谢谢。

【问题讨论】:

  • 提供独立的转换函数?
  • @ThomasMatthews:我想到了这个,但我仍然想探索将底层boost数组传递给C函数的可能性(也许这是一个糟糕的想法,但我想我应该问一下; )

标签: c++ c casting mixing


【解决方案1】:

只要源类型和目标类型都支持标准迭代器接口(对于 std::vector、数组和我能想到的每个 Boost 序列类型都是如此;所以你只需要修复你的 custom_vector),并且作为只要数字类型之间存在隐式转换,您应该可以只使用std::copy

【讨论】:

  • 我对此进行了测试,它可以工作。现在,有没有办法避免临时存储?换句话说,我可以将底层的 boost 数组传递给 C 函数吗?
  • @Arrieta:如果底层表示就像一个数组(而且几乎总是如此),&a[0] 应该可以工作。
【解决方案2】:

如果您要在这样的两种数据类型之间进行转换,您可能应该编写很多样板文件。不管你涂了多少口红,都是一样的操作。

当您看到 realtype 之类的类型定义时,对我来说这是一种代码异味,因为有人过早地抽象数据。在较低级别围绕数据编写抽象往往会使接口像这样“爆炸”。如果您以最愚蠢的方式使用数据容器,通常情况会更好。不要用它们保护不变量,只存储数据。在算法级别进行抽象,并以最简单的形式保留数据。

重构其他代码以全部使用一致的东西可能是有意义的,但通常是旧代码或外部代码。在您的新开发中,保持理智并使用向量。编写适配器以在它们之间进行转换,让旧代码继续在你的外表后面吸。

在避免这些问题变得非常笨拙方面,我最高兴的是使用指针和长度。诚然,这违背了大多数建议。

void foo(double *data, size_t len);

它会产生丑陋(且容易出错)的代码,但它是最小的公分母。如果您可以将其隐藏在私有实现中,那显然会更好。

我刚刚写了很多无法重用的助手。结果,代码的局部性很差,我的意图并不明显。

【讨论】:

  • 很棒的帖子。我特别喜欢“让旧代码继续在你的单板后面吸” - 我将以此为目标。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-12
  • 1970-01-01
  • 2016-02-23
  • 2015-10-23
  • 1970-01-01
相关资源
最近更新 更多