【问题标题】:Templates with implicit parameters, forward declaration, C++带有隐式参数、前向声明、C++ 的模板
【发布时间】:2011-02-05 09:35:33
【问题描述】:

有一个带有隐式参数的模板类声明:

列表.h

template <typename Item, const bool attribute = true>
class List: public OList <item, attribute>
{
    public:
    List() : OList<Item, attribute> () {}
    ....
};

我尝试在不同的头文件中使用后续的前向声明:

分析.h

template <typename T, const bool attribute = true>
class List;

但是 G++ 显示这个错误:

List.h:28: error: redefinition of default argument for `bool attribute'
Analysis.h:43: error:   original definition appeared here

如果我使用没有隐式参数的前向声明

template <typename T, const bool attribute>
class List;

编译器不接受这种结构

分析.h

void function (List <Object> *list)
{
}

并显示以下错误(即不接受隐式值):

Analysis.h:55: error: wrong number of template arguments (1, should be 2)
Analysis.h:44: error: provided for `template<class T, bool destructable> struct List'
Analysis.h:55: error: ISO C++ forbids declaration of `list' with no type

更新问题:

我从模板定义中删除了默认参数:

列表.h

template <typename Item, const bool attribute>
class List: public OList <item, attribute>
{
    public:
    List() : OList<Item, attribute> () {}
    ....
};

使用 List 类的第一个文件具有参数属性的隐式值的前向声明

分析1.h

template <typename T, const bool attribute = true>
class List;  //OK

class Analysis1
{
    void function(List <Object> *list); //OK
};

第二类使用类List WITH前向定义使用隐式值

分析2.h

template <typename T, const bool attribute = true> // Redefinition of default argument for `bool attribute'
class List; 

class Analysis2
{
    void function(List <Object> *list); //OK
};

第二个类使用类List WITHOUT使用隐式值进行前向定义

分析2.h

template <typename T, const bool attribute> // OK
class List; 

class Analysis2
{
    void function(List <Object> *list); //Wrong number of template arguments (1, should be 2)
};

【问题讨论】:

  • 好的,我了解您的问题。这是因为您在使用 List 的每个文件中添加了前向声明。不要那样做。而是在您使用List 的每个文件中定义 List #include "List.h"List.h 中添加前向声明。如果您仍然遇到问题,请告诉我!
  • 更新后你的问题是什么?

标签: c++ templates parameters forward-declaration implicit


【解决方案1】:

简单。从定义中删除默认值,因为您已经在前向声明中提到了这一点。

template <typename Item, const bool attribute = true> //<--- remove this 'true`
class List: public OList <item, attribute>
{
  //..
};

写:

template <typename Item, const bool attribute>  //<--- this is correct!
class List: public OList <item, attribute>
{
  //..
};

在线演示:http://www.ideone.com/oj0jK

【讨论】:

  • @Robo:如果有效,则通过单击刻度线“接受”此答案。到目前为止,您甚至没有接受一个答案!
  • @Nawaz:我宁愿将默认值放在声明中而不是前向声明中。我认为这样更清楚。
  • 如果我的程序中有更多的类使用模板类 List 和默认参数属性,是否需要在每个前向声明中添加参数的默认值?
  • @Robo:您不接受答案令人失望和沮丧。你连一个答案都不接受。为什么你认为人们会在你不接受的时候关心回答你的问题?
  • 我接受了您的回答并感谢您抽出宝贵时间...但是此模型不适用于具有模板默认参数的多个类...
【解决方案2】:

一个可能的解决方案是声明另一个头文件,List_fwd.h

template <typename Item, const bool attribute>
class List;

因此,在 List.h 和 Analysis.h 中,您在开头都包含 List_fwd.h。所以 List.h 变成了

#include "List_fwd.h"

template <typename Item, const bool attribute = true>
class List: public OList <item, attribute>
{
    public:
    List() : OList<Item, attribute> () {}
    ...
};

和分析.h

#include "List_fwd.h"

【讨论】:

    【解决方案3】:

    您必须确保只有第一个声明具有参数的默认值。这可以通过首先定义一个仅前向声明的标头,然后从List.hAnalysis.h 中包含它来实现。在List.h的定义中,不要包含默认值。

    【讨论】:

      【解决方案4】:

      您只能在一个地方定义默认参数(对于给定的翻译)。在类声明中这样做是最有用的,而在前面定义它是一个坏主意。

      转发不需要默认参数(在某些情况下您只需键入它)。

      如果你真的想要一个默认参数,你可以创建另一个简单的模板类型,它与转发一起实现这一点。然后您通过 typedef 访问结果。您可以使用 List 的转发来做到这一点。

      【讨论】:

        【解决方案5】:

        您必须在使用它的每个文件中包含List.h。声明仅适用于非模板类型。对于模板类型,您必须包含每个编译单元的头文件。

        【讨论】:

        • 但是如何避免使用这种模型的头文件中的循环延迟呢?
        • @Robo 我不是说你不能声明它,我说你必须包含头文件。要解决依赖关系,您可能必须在包含标头之前声明类。但是你偷需要包含标题
        • @Robo 顺便说一句,不需要在 include 之前声明它:)
        猜你喜欢
        • 2010-12-20
        • 1970-01-01
        • 2021-05-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-01-06
        • 1970-01-01
        相关资源
        最近更新 更多