带有前向声明的默认模板参数

发布于 2024-08-12 17:44:58 字数 820 浏览 7 评论 0原文

是否可以在不指定或不知道这些参数的情况下转发声明使用默认参数的类?

例如,我想声明一个 boost::ptr_list< TYPE > 在 Traits 类中,无需将整个 Boost 库拖到包含这些特征的每个文件中。我想申报 命名空间 boost { template;类 ptr_list< T>; },但这不起作用,因为它与真实的类声明不完全匹配:

template < class T,
    class CloneAllocator = heap_clone_allocator,
    class Allocator = std::allocator<void*>
    >
class ptr_list { ... };

我的选择只是接受它还是指定 boost::ptr_listboost::ptr_list我的特征类中的 TYPE、boost::heap_clone_allocator、std::allocator ? (如果我使用后者,我想我还必须转发声明 boost::heap_clone_allocator 并包含 。)

我已经查看了 Stroustrup 的书,SO,以及互联网的其余部分,但尚未找到解决方案。通常人们担心不包含 STL,解决方案是“只包含 STL 标头”。然而,Boost 是一个更庞大且编译器密集的库,所以除非绝对必要,否则我宁愿将其排除在外。

Is it possible to forward declare a class that uses default arguments without specifying or knowing those arguments?

For example, I would like to declare a boost::ptr_list< TYPE > in a Traits class without dragging the entire Boost library into every file that includes the traits. I would like to declare
namespace boost { template<class T> class ptr_list< T >; }, but that doesn't work because it doesn't exactly match the true class declaration:

template < class T,
    class CloneAllocator = heap_clone_allocator,
    class Allocator = std::allocator<void*>
    >
class ptr_list { ... };

Are my options only to live with it or to specify boost::ptr_list< TYPE, boost::heap_clone_allocator, std::allocator<void*> in my traits class? (If I use the latter, I'll also have to forward declare boost::heap_clone_allocator and include <memory>, I suppose.)

I've looked through Stroustrup's book, SO, and the rest of the internet and haven't found a solution. Usually people are concerned about not including STL, and the solution is "just include the STL headers." However, Boost is a much more massive and compiler-intensive library, so I'd prefer to leave it out unless I absolutely have to.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

秋心╮凉 2024-08-19 17:44:58

是的。可以随时随地指定默认模板参数,只要声明彼此不冲突即可。它们最终由各种声明合并在一起。

即使这样也是合法的:

template< class A, class B, class C = long >
class X;

template< class A, class B = int, class C >
class X;

template< class A = short, class B, class C >
class X { };

§14.1/10 中给出了类似的例子。根据该段落,函数默认参数的行为类似。

祝你好运,让前瞻性声明表现得很好,而不是对所有事情都吐槽!

Yes. Default template arguments may be specified any time, anywhere, so long as the declarations don't conflict with each other. They are ultimately merged together from the various declarations.

Even this is legal:

template< class A, class B, class C = long >
class X;

template< class A, class B = int, class C >
class X;

template< class A = short, class B, class C >
class X { };

A similar example is given in §14.1/10. According to that paragraph, function default arguments behave similarly.

Good luck on getting the forward declaration to behave itself and not barf on everything!

时光与爱终年不遇 2024-08-19 17:44:58

我认为您不能使用默认参数转发声明模板,除非相关库提供了自己的转发声明标头。这是因为你无法重新指定默认参数(即使它们匹配... gcc 仍然会报告“错误:重新定义默认参数”)。

因此,据我所知,解决方案是让库提供一个前向声明头 Foo_fwd.h:

#ifndef INCLUDED_Foo_fwd_h_
#define INCLUDED_Foo_fwd_h_
template<class T, class U=char> class Foo; // default U=char up here
#endif

然后 Foo.h 中的完整实现将是:

#ifndef INCLUDED_Foo_h_
#define INCLUDED_Foo_h_
#include "Foo_fwd.h"
template<class T, class U> class Foo { /*...*/ }; // note no U=char here
#endif

所以现在您的代码也可以使用 Foo_fwd.h...但是不幸的是,由于这种方法需要修改原始 Foo.h 以删除默认参数,因此无法扩展到第三方库。也许我们应该游说 C++0x 工作人员允许对默认模板参数进行等效的重新指定,就像 typedefs...?

I don't think you can forward declare a template with default arguments unless the library in question provided its own forward declaration header. This is because you can't respecify the default arguments (even if they match... gcc will still report “error: redefinition of default argument”).

So to the best of my knowledge the solution is for the library to supply a forward declaration header Foo_fwd.h:

#ifndef INCLUDED_Foo_fwd_h_
#define INCLUDED_Foo_fwd_h_
template<class T, class U=char> class Foo; // default U=char up here
#endif

and then the full implementation in Foo.h would be:

#ifndef INCLUDED_Foo_h_
#define INCLUDED_Foo_h_
#include "Foo_fwd.h"
template<class T, class U> class Foo { /*...*/ }; // note no U=char here
#endif

So now your code could use Foo_fwd.h as well... but unfortunately, since this approach requires modifying the original Foo.h to remove the default arguments this doesn't scale to 3rd party libraries. Maybe we should lobby the C++0x crew to allow equivalent respecification of default template arguments, à la typedefs...?

煞人兵器 2024-08-19 17:44:58

任何使用您的设施的前向声明 boost 内容的编译单元都需要包含 boost 标头,除非您有某些程序实际上不会使用设施的 boost 部分。

确实,通过前向声明,您可以避免包含此类程序的 boost 标头。但对于那些实际使用 boost 部分的程序,您必须手动包含 boost 标头(或使用 #ifdef)。

请记住,未来的 Boost 版本中可能会添加更多默认模板参数。我建议不要走这条路线。如果您的目标是加快编译时间,我会考虑使用#define 来指示是否应禁用使用该 boost 库的代码。这样您就可以避免前向声明的麻烦。

Any compilation unit that uses your facility that forward-declares boost stuff will need to include the boost headers anyway, except in the case that you have certain programs that won't actually use the boost part of your facility.

It's true that by forward-declaring, you can avoid including the boost headers for such programs. But you'll have to manually include the boost headers (or have an #ifdef) for those programs that actually use the boost part.

Keep in mind that more default template parameters could be added in a future Boost release. I'd advise against this route. What I would consider, if your goal is to speed compile times, is to use a #define to indicate whether the code using that boost library should be disabled. This way you avoid the forward declaration hassle.

雪若未夕 2024-08-19 17:44:58

好吧,这里有同样的问题。但是用STL。

如果我的标题之一使用例如。 std::vector 那么我必须包含整个标头。从此时起,每次我包含我的标头,即使我的源代码根本不引用 std::vector,标头也会与我的标头一起包含在内。如果您在很多地方包含此标头,则意味着大量过度解析。

因此,我向前声明了 std::vector 并使用了 std::vector* ,但由于默认参数,我的代码不想编译。如果我将默认参数放在标头中,则编译器会由于默认参数尊重而拒绝编译 stl 标头。

在这种情况下我想做的是创建我自己的 Vector 类,该类适应 std::vector 并将每个方法调用转发给它。也许这可以解决问题。

Well same issue here. But with STL.

If one of my header use eg. std::vector then I have to include the entire header. From this time every time I include my header even if my source code does not refer to std::vector at all the header gets included along with my header. If you include this header in lots of place that will mean lots of overparsing.

So I forward declared the std::vector and used std::vector* 's but my code don't want to compile due to the default arguments. If I place the default arguments in my header then the compiler refuses to compile the stl header due to the default argument respectification.

What I'm trying to do in this situation is creating my own Vector class that adapts the std::vector and forwards every method call to it. Probably this could solve the problem.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文