Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ template class behaves differently for different compilers

I am working with templates in C++. Is there any difference in using templates and friend class when compiled with MSVC compiler and when using Mingw gcc compiler. My code successfully compiles and gives the desired output when compiled with MSVC but it gives error when compiled with gcc. Below is my code,

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

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

When compiled the above code with MSVC gives desired output but when compiled with Mingw GCC compiler it gives following error,

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

What could be the possible solution to this problem? Thanks in advance.

like image 640
user2765235 Avatar asked Oct 11 '13 12:10

user2765235


People also ask

What is the main problem with templates C++?

Can get complicated quickly if one isn't careful. Most compilers give cryptic error messages. It can be difficult to use/debug highly templated code. Have at least one syntactic quirk ( the >> operator can interfere with templates)

How many times are template classes compiled?

In general, yes, template classes are usually compiled every time they're encountered by the compiler.

What are templates and how does the compiler interpret them?

In other words, a template is a mechanism that allows a programmer to use types as parameters for a class or a function. The compiler then generates a specific class or function when we later provide specific types as arguments.

Is template a keyword in C?

C++ template is also known as generic functions or classes which is a very powerful feature in C++. A keyword “template” in c++ is used for the template's syntax and angled bracket in a parameter (t), which defines the data type variable.


1 Answers

MSVC does not implement two-phase name lookup correctly. GCC is correct in reporting this error.

The cause is that names used inside a template which do not depend on the template's parameters are (should be in the case of VC) looked up when the template is defined, not when it's instantiated.

In your case, the compiler has no way of telling that IsNonValid will come from the base class, so it rightfully complains it doesn't know it. There are two possible solutions:

  1. Qualify the access to IsNonValid, so that it's clear to the compiler it (potentially) depends on the template parameters:

    QString val = this->IsNonValid() ? "Non" : "";
    
    // or
    
    QString val = TYPE_LIST::IsNonValid() ? "Non" : "";
    
  2. Introduce the inherited name into the scope of the derived class:

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

Either of these will make the name dependent and thus postpone its lookup until instnatiation, when the value of TYPE_LIST is actually known.

like image 87
Angew is no longer proud of SO Avatar answered Sep 26 '22 06:09

Angew is no longer proud of SO