对最终用户不可访问的模板化和非模板化函数混合的正确组织 [英] Proper organization for a mixture of templated and non-templated functions not accessible to the end-user

查看:93
本文介绍了对最终用户不可访问的模板化和非模板化函数混合的正确组织的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我正在开发的项目中,我目前正在实现一个模板化的算法。我有一些问题组织我的函数声明和定义,因为模板涉及(我问了一个问题在这里如何处理 功能模组化)。



我想从全部 分隔所有的定义



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




  • 所有函数声明的声明文件 algo.h
  • 定义文件 algo.tpp 将包含在 algo.h (templates在编译时需要声明)

  • 不包括(非模板)定义文件 algo.cpp



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




  • 声明文件 algo.h 只包含适用于最终用户的声明(可以通过include访问)

  • 这些函数的定义将转到 algo.cpp

  • 子功能将仅存在于 algo.cpp 中,从而允许我在大函数 > algo.cpp (在 algo.h 中声明的一个)来使用它们,但是不允许它们被最终用户访问。 li>


如果这些子功能不是模板化的,而是被模板化的函数使用, strong>模板化的子功能可以进入 .tpp 文件,由模板化的大功能使用,一切都很好。



但是,如果这些功能是非模板化的,它们会导致一个多个定义错误(这是 .tpp 文件中,那么我的上一个问题是。另一方面,如果它们在单独的 .cpp 文件中,它们或者变得可以被最终用户访问(如果我把声明放在 .h 文件),或者无法访问大功能意味着使用它们(如果我不把声明放在 .cpp 文件)。



什么是组织函数的正确方法,一些模板化和一些不是,其中一些应该是可访问的



理想情况下,(为了完整性),我要查找的答案将解决放置以下内容(在 .h .tpp .cpp 或其他适当的文件):




  • 模板客户端函数

  • 客户端函数

  • 模板客户端函数

  • 非模板客户端函数

  • 使用声明时)






短伪码 (不带文件分隔)

 模板子功能,由bigFunctionality使用,
//但是最终用户无法访问
//这可能是不可能的,因为它是模板化的,
//所以我是内容将它放在.tpp文件
模板< typename比较>
void subFunctionality(比较顺序,.. args ..){/ * impl * /}

//非模板化子功能,由
// bigFunctionality使用,但最终用户不能访问
void moreSubFunctionality(.. args ..){/ * impl * /}


//主要功能,意味着
//所有文件中的每个人都可以访问:
template< typename Compare>
void bigFunctionality(.. non-templated args ...,比较顺序){
subFunctionality(order,.. args ..);
moreSubFun(.. args ..);
//更多的东西
}

将它分成多个文件(即使它们包含在彼此中,因为它必须用模板完成),部分是为了可读性,部分是为了可访问性。



只是为了说明,这些是算法 - >函数,而不是类。 (我知道把模板和非模板化的函数放在同一个模板类中可以解决我的问题)。



PS:

的问题, h2_lin>解决方案

这是C ++中缺少模块的一个不幸的副作用:声明的内容必然可见。



一般来说,指南是简单地使用私有命名空间(嵌套在用户可见的命名空间内):




  • 使用一个清楚的名称(例如 internal

  • ,并且仅在中的那个命名空间中声明这些帮助函数。 tpp 文件



然后,记录此命名空间是内部的,不适合客户端调用。如果可能的话,你还要注释命名空间/函数,以便不为它们生成文档。



这时,这些函数是

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



(*) code>基本上替换了私有命名空间。


In a project I am working on, I am currently implementing an algorithm which is templated. I had some problems organizing my function declarations and definitions, because templates are involved (I asked a question here about how to deal with non-templated functions "grouped" together with the templated ones). This, however, made me wonder about a general proper organization of such files.

I wanted to separate all the definitions from all the declarations (just for readability purposes, even if I had to include templated definitions back into declarations).

The answers I got suggested organization such as this:

  • The declarations file algo.h for all the function declarations
  • The templated definitions file algo.tpp which will be included in algo.h (templates need declarations at compile time)
  • The (non-templated) definitions file algo.cpp not included anywhere.

This works well if all the defined functions are supposed to be visible to the end-user (i.e. all the declarations are in the algo.h file). However, sometimes I like to break my big functions into smaller functionalities, but I would like the end-user to be able to access only the "big function" and not their sub-parts. In a non-templated set-up, I would do this in this way:

  • The declarations file algo.h would contain only the declarations meant for the end-user (which will become accessible through the include)
  • The definitions of those functions would go to algo.cpp
  • The definitions (and declarations) of the sub-functionalities would only be present in the algo.cpp, allowing my big function in algo.cpp (the one declared in algo.h) to use them, but not making them accessible to the end-user.

This does not work any more if those sub-functionalities are not themselves templated, but are used by the templated function. The templated sub-functionalities can go into the .tpp file, get used by the templated "big function", and everything is good.

However, if those functionalities are non-templated, they would cause a multiple definitions error (which is what my previous question was about) if placed in the .tpp file. On the other hand, if they are in the separate .cpp file, they either become accessible to the end-user (if I put the declarations in the .h file), or become inaccessible to the big function meant to use them (if I do not put the declarations outside the .cpp file).

What is the proper way of organizing functions, some templated and some not, some of which are supposed to be accessible to the end-user, and some not, into multiple files?

Ideally, (for completeness), the answer I'm looking for would address the placement of the following (in the .h, .tpp, .cpp, or other appropriate files):

  • templated client functions
  • non-templated client functions
  • templated client functions
  • non-templated client functions
  • declarations of all of the above (when declarations are used)

Short almost-pseudo-code example of the functionality I want to have (without the file-separation)

    // 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
    }

Once again, I am looking how to separate this in to multiple files (even if they are included in each other, as it has to be done with templates), partially for readability purposes and partially for accessibility.

Just for clarifications, these are algorithms --> functions, and not classes. (I know that putting templated and non-templated functions in to the same templated class would solve my problems).

PS: I know the title of the question is very big and long, so if somebody has an idea about shortening it, I would be more than happy for the suggestions/edits

解决方案

This is an unfortunate side-effect of the absence of modules in C++: what is declared is necessarily visible.

In general, the guideline is to simply use a "private" namespace (nested within the user-visible namespace(s)):

  • use a clear name (such as internal)
  • and declare those helper functions only in that namespace in your .tpp file

Then, you document that this namespace is internal and non-suitable for client callers. If possible, you also annotate the namespace/functions so that no documentation is generated for them.

At this point, those functions are clearly private and hidden.

If you wish to go one step further, you may simply declare them private in a class (*), and then have only your functions be friend of this class. Then, any attempt to use them will result in the compiler emitting an error: they are visible, but not accessible. However, most people (starting with Boost developers) just do not bother, and I certainly do not either.

(*) The class essentially replaces the private namespace.

这篇关于对最终用户不可访问的模板化和非模板化函数混合的正确组织的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆