Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I have g++ mimic MSVC++'s template instantiation behavior?

I'm trying to port my own lib from Visual Studio to g++ on GNU/Linux, and I'm getting some problems with template compilation. Indeed, in Visual C++, templates are generated only when they are explicitly used in the code, while it seems (from my errors) that g++ evaluates the contents of templates before they are first used. This results in the following error:

error: incomplete type ‘X’ used in nested name specifier

... because I include some classes after the template code, rather than before. I am doing this due to a cross-use conflict.

To sum it seems that Visual C++ does not attempt to resolve templates' content on use, and g++ does resolution as soon as possible.

class MyClass;
template<class _Ty>
void func(MyClass* a_pArg)
{ 
   a_pArg->foo();
};

(_Ty isn't used but it doesn't matter, it's just to explain the problem)

In that case Visual C++ would compile (even if MyClass isn't predeclared), while g++ will not, because MyClass hasn't been completely declared.

Is there a way to tell g++ to instantiate templates only on use?

like image 332
Juicebox Avatar asked Jun 20 '11 23:06

Juicebox


3 Answers

As it was indicated in another answer, gcc is correct looking up non-dependent names in the first lookup phase, and VC++ shifts most checks to the second phase (which is incorrect). In order to fix your code, you don't need to search for some broken version of gcc. You need to separate the declaration and implementation (at least for non-dependent names). Using your example,

// provide declarations
class MyClass;

template<class T>
void func(MyClass* a_pArg);

// provide definition of MyClass
class MyClass
{
   // watever
};

// provide definition of func
template<class T>
void func(MyClass* a_pArg);
{ 
   a_pArg->foo();
};
like image 23
Gene Bushuyev Avatar answered Nov 13 '22 05:11

Gene Bushuyev


If you are willing to use CLang instead of gcc, CLang support the -fdelayed-template (dedicated to perform template instantiation at the end of the parsing) implied by -fms-extensions option specifically designed to compile MSVC code (and numerous quirks).

According to Francois Pichet, who is leading CLang effort to fully compile MSVC code (and actually doing most of it), CLang should be able to parse all of MFC code in about 2 to 3 months, with only a couple of non-trivial issues remaining. Already most of MFC is correctly interpreted (ie, interpreted as VC++ does).

like image 33
Matthieu M. Avatar answered Nov 13 '22 06:11

Matthieu M.


No, that's the way two-phase lookup works. MSVC implements it wrong, it nearly skips the first phase, which parses the template at the point of definition. MSVC only does some basic syntax checking here. In the second phase, on actual use of the template, the dependent names should only be inspected. MSVC does all kind of parsing here instead. GCC implements the two-phase lookup correctly.

In your case, since MyClass isn't a template parameter, it can inspect it in phase one. You just need to include your class header before that.

like image 56
Xeo Avatar answered Nov 13 '22 07:11

Xeo