在API中处理复杂的嵌套类型

时间:2019-10-24 12:58:00

标签: c++ types architecture api-design naming

因此,我们假设有一个与图像处理有关的项目。我们有一种算法可以计算两个图像之间的“分数”(无论是什么):

double score(Image i1, Image i2)

如果我们有多个帧(图像),我们想为所有这些帧(图像全部匹配)进行计算:

std::vector<std::pair<std::pair<int, int>, double>> score(std::vector<Image> images); // [1]

整数对表示图像向量中的图像索引,因为我们将所有人都匹配

不幸的是,我们从许多设备中获取图像,其中每个设备都可以具有多个流(然后每个流中都有多个连续的帧),这使此过程变得复杂:

std::vector<std::vector<std::vector<std::pair<std::pair<int, int>, double>>>>
     ^devices    ^streams    ^frames     ^score   ^image indices

您将如何处理必须返回这种复杂类型的函数?

这仅仅是关于将其包装在typedef中并正确命名吗?或者,也许您只允许用户使用更简单的API版本,即使用一个矢量[1],然后进一步将它们自己包装?也许对于这种情况有什么幻想的方式吗?

2 个答案:

答案 0 :(得分:1)

通常,您通过给事物起个适当的名称来处理复杂性。

当我在[1]中看到您的API时,会看到一个图形,其中图像是图形的节点,并且您将边缘作为邻接列表返回。邻接信息也可以以对称邻接矩阵的形式存储。掌握适合您问题的术语,可能会为您提供各种工具,例如Boost.Graph之类的库。这可能是您编写自己的可重用组件的起点。您甚至可能发现人们正在处理您要解决的问题,但是用的是抽象的术语。

这只是一种选择,当您考虑正确命名时,可能会发生美好的事情。

关于您的第二次复杂度提升,我认为调用者可能要决定他们想要输入到算法中的块的大小,因为这似乎在人为地限制了函数的用例。如果您认为并非如此,则仍应给这些事物起适当的名称。您可以为其使用结构和类,这种选择可能很差:

using AdjacencyList = std::vector<std::pair<std::pair<int, int>, double>;
// Info that might also be represented as a matrix or symmetric matrix.

class SimilarityData
{
    public:
        const AdjacencyList &
        getAdjacencyList(
            int device,
            int stream,
            int frame ) const;
};

答案 1 :(得分:0)

在不了解太多数据的情况下,一种选择是创建用于包装各个部分的结构或类:

namespace your_company {
struct index {
    std::pair<int, int> indexes;
};
struct frame {
    std::pair<index, double> scores;
};
struct stream {
    std::vector<frame> frames;
};
struct device {
    std::vector<stream> streams;
};
}

如果需要,您甚至可以将更多信息添加到结构中。如:

struct device {
    std::vector<stream> streams;
    std::string name;
};

因此,您的函数将返回device。用户代码可能类似于:

your_company::device d = your_function();
d.streams[0].frames[0].scores[0].pair[0].....
相关问题