正确组织最终用户无法访问的模板化和非模板化功能

Proper organization for a mixture of templated and non-templated functions not accessible to the end-user

本文关键字:功能 访问 用户      更新时间:2023-10-16

在我正在做的一个项目中,我目前正在实现一个模板化的算法。我在组织函数声明和定义时遇到了一些问题,因为涉及到模板(我在这里问了一个关于如何处理非模板函数与模板函数"分组"在一起的问题)。然而,这使我对这些文件的一般正确组织产生了疑问。

我想把所有的定义所有的声明分开(只是为了可读性,即使我不得不在声明中包含模板化的定义)。

我得到的答案建议组织如下:

  • 所有函数声明的声明文件algo.h
  • 模板化的定义文件algo.tpp将包含在algo.h中(模板需要在编译时声明)
  • (非模板化的)定义文件algo.cpp不包含在任何地方。

如果所有定义的函数都应该对最终用户可见(即所有声明都在algo.h文件中),则此方法工作得很好。然而,有时我喜欢把我的大函数分解成更小的功能,但是我希望最终用户只能访问"大函数",而不能访问它们的子部分。在非模板设置中,我会这样做:

  • 声明文件algo.h将只包含用于最终用户的声明(可通过include访问)
  • 这些函数的定义将进入algo.cpp
  • 子功能的定义(和声明)将只出现在 algo.cpp中,允许我的大函数algo.cpp中使用它们(在algo.h中声明的那个),但不能使最终用户访问它们。

如果这些子功能本身没有被模板化,而是被模板化的函数使用,则不再工作。模板化的子功能可以放到.tpp文件中,由模板化的"大函数"使用,一切都很好。

然而,如果这些功能是非模板化的,如果放在.tpp文件中,它们将导致多个定义错误(这就是我之前的问题)。另一方面,如果它们在单独的.cpp文件中,它们要么对最终用户可访问(如果我将声明放在.h文件中),要么对打算使用它们的大函数不可访问(如果我没有将声明放在.cpp文件之外)。

组织函数的正确方式是什么,有些是模板化的,有些不是,其中一些应该是最终用户可以访问的,而有些不是,放在多个文件中?

理想情况下,(为了完整性),我正在寻找的答案将解决以下问题(在.h, .tpp, .cpp或其他适当的文件中):

  • 模板化客户端函数
  • 非模板客户端函数
  • 模板化客户端函数
  • 非模板客户端函数
  • 上述所有声明(当使用声明时)

简短的伪代码我想要的功能示例(没有文件分隔)

    // Templated sub-functionality, used by bigFunctionality,
    // but ideally not accessible to the end-user
    // This might not be possible since it is templated,
    // so I am content with putting it in the .tpp file
    template <typename Compare>
    void subFunctionality(Compare order, .. args ..){ /* impl */ }
    // Non-templated sub-functionality, used by
    // bigFunctionality, but NOT accessible to the end-user
    void moreSubFunctionality(.. args ..) { /* impl */ }

    // the main functionality, meant to be
    // accessible to everybody across all files:
    template <typename Compare>
    void bigFunctionality( .. non-templated args ..., Compare order){
         subFunctionality(order, .. args ..);
         moreSubFun(.. args ..);
         // more stuff
    }

再一次,我正在寻找如何将其分离到多个文件(即使它们彼此包含在一起,因为它必须与模板一起完成),部分出于可读性目的,部分出于可访问性。

澄清一下,这些是算法-->函数,而不是类。(我知道将模板化和非模板化的函数放入同一个模板化类中可以解决我的问题)。

PS:我知道问题的标题又大又长,所以如果有人有缩短它的想法,我将非常高兴得到建议/编辑

这是c++中没有模块的一个不幸的副作用:声明的内容必须是可见的。

一般来说,指导方针是简单地使用"私有"命名空间(嵌套在用户可见的命名空间中):
  • 使用清晰的名称(如internal)
  • 并在.tpp文件
  • 的命名空间中声明这些辅助函数

然后,说明这个名称空间是内部的,不适合客户端调用者。如果可能的话,还应该注释命名空间/函数,这样就不会为它们生成文档。

此时,这些函数是明显私有的隐藏的

如果你想更进一步,你可以简单地在class(*)中声明它们private,然后只有你的函数是这个类的friend。然后,任何使用它们的尝试都会导致编译器发出一个错误:它们是可见的,但是不可访问。然而,大多数人(从Boost开发人员开始)只是不麻烦,我当然也不会。

(*) class基本上取代了私有命名空间。