【问题标题】:C++ template class behaves differently for different compilers对于不同的编译器,C++ 模板类的行为不同
【发布时间】:2013-10-19 13:38:05
【问题描述】:

我正在使用 C++ 中的模板。使用 MSVC 编译器编译和使用 Mingw gcc 编译器时,使用模板和友元类有什么区别。我的代码在使用 MSVC 编译时成功编译并提供了所需的输出,但在使用 gcc 编译时出现错误。下面是我的代码,

///////////Record.h/////////////////////
#include "Base.h"

class Derived1;
class Derived2;
template <class TYPE_LIST> class List;

class FRecord
{
public:
    FRecord();
    virtual ~FRecord();

    friend class Base;
#if _MSC_VER <= 1200
    friend class List<Derived1>;
    friend class List<Derived2>;
#else
    template <class TYPE_LIST> friend class List;
#endif
};

///////////////////////////////////////////////////////////////

///////////////////Base.h/////////////////////////////////

class Base
{
public:
    Base(const HEADER *hc, const FRecord *fr);
    virtual ~Base();    
    __inline bool IsNonValid() const;

protected:
    quint32 Size;
};

/////////////////////////////////////
// Data
/////////////////////////////////////
template <class TYPE_LIST>
class Data : public TYPE_LIST
{
public:
    Data(const HEADER *hc, const FRecord *fr) : TYPE_LIST(hc, fr)
    {
        QString val = IsNonValid() ? "Non" : "";
        LOG0("Data ("<<  val << " Valid)");
    }

    virtual ~Data()
    {
        LOG0("Data deleted");
    }
};  // Data

///////////////////////////////////////////////////////////////////////////////////////

当使用 MSVC 编译上述代码时,会得到所需的输出,但使用 Mingw GCC 编译器编译时会出现以下错误,

Base.h:1154: error: there are no arguments to 'IsNonValid' that depend on a template parameter, so a declaration of 'IsNonValid' must be available
Base.h:1553: error: 'Size' was not declared in this scope

这个问题的可能解决方案是什么? 提前致谢。

【问题讨论】:

    标签: c++ qt templates mingw32 visual-studio-2010


    【解决方案1】:

    MSVC 未正确实现两阶段名称查找。 GCC 报告这个错误是正确的。

    原因是模板中使用的不依赖于模板参数的名称(应该在 VC 的情况下)在定义模板时查找,而不是在实例化模板时查找。

    在您的情况下,编译器无法告诉 IsNonValid 将来自基类,因此它理所当然地抱怨它不知道它。有两种可能的解决方案:

    1. 限定对IsNonValid的访问,以便编译器清楚它(可能)取决于模板参数:

      QString val = this->IsNonValid() ? "Non" : "";
      
      // or
      
      QString val = TYPE_LIST::IsNonValid() ? "Non" : "";
      
    2. 将继承的名字引入派生类的作用域:

      template <class TYPE_LIST>
      class Data : public TYPE_LIST
      {
      public:
        using TYPE_LIST::IsNonValid;
        // the rest as you had it originally
      

    其中任何一个都会使名称依赖并因此将其查找推迟到实例化,此时TYPE_LIST 的值实际上是已知的。

    【讨论】:

    • 感谢@Angew:您的解决方案解决了我的问题。:)..现在我如何将问题的状态更改为 SOLVED?
    • @user2765235 通过接受您认为解决问题的答案。您可以通过单击答案旁边的绿色对勾来完成此操作。请参阅help 了解更多信息。
    【解决方案2】:

    gcc 是正确的。您需要添加this-&gt; 以延迟查找直到实例化时间。

    this-&gt;IsNonValid();

    MSVC 不符合标准,因为它没有正确实现两阶段名称查找,因此它会将所有查找延迟到实例化时间。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-03
      • 1970-01-01
      • 2013-03-08
      • 2011-02-09
      • 2013-05-16
      相关资源
      最近更新 更多