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?
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.
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();
};
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).
Visual C++ doesn't implement by default two-phase lookup specified by the standard.
However, looks like two-phase lookup is a bit better in Visual Studio 2015 with /Za option. Perhaps you can do the opposite by adding /Za option to mimic GCC template instantiation behavior for some cases.
Related
Today, I encountered a compile issue in clang that surprised me. I guess is reasonable but I like to dig deeper and hear more details. Some standard references if possible also.
I have a class with a template method which rely on a member which his type is undefined in the header (but not in the source). Something like the following:
// Menu.h
class Page;
class Menu
{
public:
.... // stuff
template<class Visitor>
void VisitWidget( Visitor&& visitor);
private:
std::unique_ptr<Page> m_page; // destructor implemented in source file, so Page is an incomplete type
};
template<class Visitor>
inline void Menu::VisitWidget( Visitor&& visitor);
{
m_page->Visit( std::forward<Visitor>(visitor) );
}
In VisualStudio, it compiles. I expect this to only complain when instanciating; so inlining. However, in clang, this doesn't compile as soon as someone includes the header. Forcing me to include Page.h in Menu.h (which I want to avoid at all cost).
Like:
// Another.cpp (not Menu.cpp)
#include "Menu.h" // this trigger and error due Page is an incomplete type
even if the whole Another.cpp is not using VisitWidget (even in other headers)
I guess that this is caused by inline somehow, since the compiler is not obligated to really use it, but since there are templates in the middle I am not so sure. Is really clang checking the type?
Yes, this compiles in MSVC because it has a well-known bug. It doesn't implement two-step template instantiation.
To elaborate. MSVC wrongly defers template parsing until it is actually instantiated in the code. Likely it happens after full Page definition becomes visible.
However, standard demands that the template is pre-parsed at the point of definition, and all types which are not dependent on template arguments are resolved. This fails, since m_page is not dependent on visitor argument - and it is still incomplete type at this point.
P.S. I can't even express how outraged I am at MSFT for this blatant Standard violation (among others). It makes cross-platform development a real pain, when MS-compliant code has to be ported to conforming compilers.
I'm looking for an overview or description of what GCC does differently than MSVC for compile + link of template classes with specializations. For example, this type of thing works on GCC but not MSVC:
// Base.h
template <typename T> struct Base {
template <class G> QString makeTitle(const G* obj){obj->CompilerError();}
};
// in Foo.cpp
template <> template <class G> QString Base<T_1>::makeTitle(const G* obj) { return mystr(); }
void SomeFunc() {
std::cout<< Base<T_1>().makeTitle<myclass>() ;
}
and the solution tends to be that I must declare the specialization in Base.h before using it, or on windows there is a link error. How/why does MSVC implicitly instantiate differently, and how/why is GCC robust to the specialization being declared in some cpp file?
related question that notes the general 'declare before using' requirement: Template specialization - different behaviour between MSVC and GCC/MinGW
The first thing is that your code is in violation of the ODR rule if any translation unit includes the header and causes the definition of the specialization without the compiler seeing a declaration. Since that is undefined behavior the fact that one compiler accepts it and the other rejects it is well within reason.
The correct code, as you already figured out is to provide the declaration of the specialization, and that will work in any compiler.
As of why it seems to work or even why does it actually work in gcc, this is most probably a matter of how the code is generated and the linker processes the object files. In particular in gcc the compiler will generate the specialization in the translation unit that needs it (and does not see your own specialization), but it will be marked as a weak symbol. The gcc linker will accept a symbol being multiply defined if all but [at most] one definitions are weak, leaving the strong symbol in the final executable.
I was trying out some CUDA/Thrust code on Linux/GCC and wanted to use some TR1 libraries, when I noticed something peculiar: Most libraries will invariably pull in tr1_impl/type_traits (4.4) or just type_traits (4.6), and that header will always contain variadic templates, like so:
template<typename _Res, typename... _ArgTypes>
struct is_function<_Res(_ArgTypes...)>
: public true_type { };
However, these headers also get used when I run GCC in C++98 or C++03 mode! How can this work?
The actual problem I encountered is that the CUDA toolchain doesn't recognize C++0x constructions, and cudafe++ (the CUDA front end, i.e. the program that separates the joint source code into host and device source code) rightly aborts with an error when encountering the variadic template parameter.
So... how can GCC support and rely on variadic templates in non-0x dialects of C++? And is there a way to obtain a genuine C++03 version of TR1?
Welp, an implementation is not required to provide headers. It's required that an #include <stuff> does The Right Thing. So that means that if an implementation decides to use headers for this functionality, it's not required that those headers be conforming C++. And in fact GCC has supported variadic templates as an extension for quite some time.
Furthermore, I can't help but notice
#pragma GCC system header
in the <tr1/random> header that you mention. GCC will treat the file specially, and e.g. not report errors warnings in it. I would have thought using an extension in conforming mode can easily be turned into an error so I'm not sure what's going on but at least legally it's an option.
There's also the special status of TR1, which is not binding. On my implementation as far I can tell the only C++03 header that includes <type_traits> is <functional> and it properly only does that in C++0x mode (i.e. the rest of the time it's a valid C++03 file via preprocessing, unlike <tr1/random>). (I didn't check for other cases though.)
I know that in the original C++0x standard there was a feature called export.
But I can't find a description or explanation of this feature. What is it supposed to do? Also: which compiler is supporting it?
Although Standard C++ has no such requirement, some compilers require that all function templates need to be made available in every translation unit that it is used in. In effect, for those compilers, the bodies of template functions must be made available in a header file. To repeat: that means those compilers won't allow them to be defined in non-header files such as .cpp files. To clarify, in C++ese this means that this:
// ORIGINAL version of xyz.h
template <typename T>
struct xyz
{
xyz();
~xyz();
};
would NOT be satisfied with these definitions of the ctor and dtors:
// ORIGINAL version of xyz.cpp
#include "xyz.h"
template <typename T>
xyz<T>::xyz() {}
template <typename T>
xyz<T>::~xyz() {}
because using it:
// main.cpp
#include "xyz.h"
int main()
{
xyz<int> xyzint;
return 0;
}
will produce an error. For instance, with Comeau C++ you'd get:
C:\export>como xyz.cpp main.cpp
C++'ing xyz.cpp...
Comeau C/C++ 4.3.4.1 (May 29 2004 23:08:11) for MS_WINDOWS_x86
Copyright 1988-2004 Comeau Computing. All rights reserved.
MODE:non-strict warnings microsoft C++
C++'ing main.cpp...
Comeau C/C++ 4.3.4.1 (May 29 2004 23:08:11) for MS_WINDOWS_x86
Copyright 1988-2004 Comeau Computing. All rights reserved.
MODE:non-strict warnings microsoft C++
main.obj : error LNK2001: unresolved external symbol xyz<T1>::~xyz<int>() [with T1=int]
main.obj : error LNK2019: unresolved external symbol xyz<T1>::xyz<int>() [with T1=int] referenced in function _main
aout.exe : fatal error LNK1120: 2 unresolved externals
because there is no use of the ctor or dtor within xyz.cpp, therefore, there is no instantiations that needs to occur from there. For better or worse, this is how templates work.
One way around this is to explicitly request the instantiation of xyz, in this example of xyz<int>. In a brute force effort, this could be added to xyz.cpp by adding this line at the end of it:
template xyz<int>;
which requests that (all of) xyz<int> be instantiated. That's kind of in the wrong place though, since it means that everytime a new xyz type is brought about that the implementation file xyz.cpp must be modified. A less intrusive way to avoid that file is to create another:
// xyztir.cpp
#include "xyz.cpp" // .cpp file!!!, not .h file!!
template xyz<int>;
This is still somewhat painful because it still requires a manual intervention everytime a new xyz is brought forth. In a non-trivial program this could be an unreasonable maintenance demand.
So instead, another way to approach this is to #include "xyz.cpp" into the end of xyz.h:
// xyz.h
// ... previous content of xyz.h ...
#include "xyz.cpp"
You could of course literally bring (cut and paste it) the contents of xyz.cpp to the end of xyz.h, hence getting rid of xyz.cpp; it's a question of file organization and in the end the results of preprocessing will be the same, in that the ctor and dtor bodies will be in the header, and hence brought into any compilation request, since that would be using the respective header. Either way, this has the side-effect that now every template is in your header file. It could slow compilation, and it could result in code bloat. One way to approach the latter is to declare the functions in question, in this case the ctor and dtor, as inline, so this would require you to modify xyz.cpp in the running example.
As an aside, some compilers also require that some functions be defined inline inside a class, and not outside of one, so the setup above would need to be tweaked further in the case of those compilers. Note that this is a compiler issue, not one of Standard C++, so not all compilers require this. For instance, Comeau C++ does not, nor should it. Check out http://www.comeaucomputing.com/4.0/docs/userman/ati.html for details on our current setup. In short, Comeau C++ supports many models, including one which comes close to what the export keyword's intentions are (as an extension) as well as even supporting export itself.
Lastly, note that the C++ export keyword is intended to alleviate the original question. However, currently Comeau C++ is the only compiler which is being publicized to support export. See http://www.comeaucomputing.com/4.0/docs/userman/export.html and http://www.comeaucomputing.com/4.3.0/minor/win95+/43stuff.txt for some details. Hopefully as other compilers reach compliance with Standard C++, this situation will change. In the example above, using export means returning to the original code which produced the linker errors, and making a change: declare the template in xyz.h with the export keyword:
// xyz.h
export
// ... ORIGINAL contents of xyz.h ...
The ctor and dtor in xyz.cpp will be exported simply by virtue of #includeing xyz.h, which it already does. So, in this case you don't need xyztir.cpp, nor the instantiation request at the end of xyz.cpp, and you don't need the ctor or dtor manually brought into xyz.h. With the command line shown earlier, it's possible that the compiler will do it all for you automatically.
See this explanation for its use
Quite a few compilers don't support it either because it's too new or in the case of gcc - because they disaprove.
This post describes standard support for many compilers.
Visual Studio support for new C / C++ standards?
See here and here for Herb Sutter's treatment of the subject.
Basically: export has been implemented in only one compiler - and in that implementation, export actually increases the coupling between template definition and declaration, whereas the only point in introducing export was to decrease this coupling.
That's why most compilers don't bother. I would have thought they would have just removed export from the language in C++0x, but I don't think they did. Maybe some day there will be a good way to implement export that has the intended use.
To put it simply:
export lets you separate the declaration (ie. header) from the definition (ie. the code) when you write your template classes. If export is not supported by your compiler then you need to put the declaration and definition in one place.
Export is a feature that introduces a circular dependency between linker and compiler. As others noted, it allows one translation unit to contain the definition of a template used in another. The linker will be the first to detect this, but it needs the compiler for the instantiation of the template. And this involves real hard work, like name lookup.
Comeau introduced it first, about 5 years ago IIRC. It worked quite well on the first beta release I got. Even testcases like A<2> using B<2> using A<1> using B<1> using A<0>, worked, if templates A and B came from different TU's. Sure, the linker was repeatedly invoking the compiler, but all name lookups worked OK. Instantiation A<1> found names from A.cpp that were invisible in B.cpp.
Standard Features Missing From VC++ 7.1. Part II: export
The only compilers that support exported templates at the moment (as far as I know) are Comeau, the one that came with Borland C++ Builder X but not the current C++ Builder, and Intel (at least unofficially, if not officially, not sure).
Suppose I have fileA.h which declares a class classA with template function SomeFunc<T>(). This function is implemented directly in the header file (as is usual for template functions). Now I add a specialized implementation of SomeFunc() (like for SomeFunc<int>()) in fileA.C (ie. not in the header file).
If I now call SomeFunc<int>() from some other code (maybe also from another library), would it call the generic version, or the specialization?
I have this problem right now, where the class and function live in a library which is used by two applications. And one application correctly uses the specialization, while another app uses the generic form (which causes runtime problems later on). Why the difference? Could this be related to linker options etc? This is on Linux, with g++ 4.1.2.
It is an error to have a specialization for a template which is not visible at the point of call. Unfortunately, compilers are not required to diagnose this error, and can then do what they like with your code (in standardese it is "ill formed, no diagnostic required").
Technically, you need to define the specialization in the header file, but just about every compiler will handle this as you might expect: this is fixed in C++11 with the new "extern template" facility:
extern template<> SomeFunc<int>();
This explicitly declares that the particular specialization is defined elsewhere. Many compilers support this already, some with and some without the extern.
Have you added a prototype with parameters to your header file?
I mean is there somewhere in fileA.h
template<> SomeFunc<int>();
If not that's probably the reason.
I had the same problem with gcc4, here is how i solved it. It was more simple a solution than what i was lead to believe by previous comments. The previous posts ideas were correct but their syntax didn't work for me.
----------header-----------------
template < class A >
void foobar(A& object)
{
std::cout << object;
}
template <>
void foobar(int);
---------source------------------
#include "header.hpp"
template <>
void foobar(int x)
{
std::cout << "an int";
}
Per the specs, your specialized function template should never be called outside fileA.C, unless you export the template definition, which no compiler (except Comeau) currently supports (or has it planned for the forseeable future).
On the other hand, once the function template is instantiated, there is a function visible to the compiler that is no longer a template. GCC may re-use this definition across different compiler units because the standard states that each template shall only be instantiated once for a given set of type arguments [temp.spec]. Still, since the template is not exported, this should be limited to the compilation unit.
I believe that GCC may expose a bug here in sharing its list of instantiated templates across compilation units. Normally, this is a reasonable optimization but it should take function specializations into account which it doesn't seem to do correctly.
In Microsoft C++, I did an experiment with inline functions. I wanted to know what would happen if I defined incompatible versions of a function in different sources. I got different results depending on whether I was using a Debug build or a Release build. In Debug, the compiler refuses to inline anything, and the linker was linking the same version of the function no matter what was in scope in the source. In Release, the compiler inlined whichever version had been defined at the time, and you got differing versions of the function.
In neither case were there any warnings. I kind of suspected this, which is why I did the experiment.
I assume that template functions would behave the same, as would other compilers.
As Anthony Williams says, the extern template construct is the correct way to do this, but since his sample code is incomplete and has multiple syntax errors, here's a complete solution.
fileA.h:
namespace myNamespace {
class classA {
public:
template <class T> void SomeFunc() { ... }
};
// The following line declares the specialization SomeFunc<int>().
template <> void classA::SomeFunc<int>();
// The following line externalizes the instantiation of the previously
// declared specialization SomeFunc<int>(). If the preceding line is omitted,
// the following line PREVENTS the specialization of SomeFunc<int>();
// SomeFunc<int>() will not be usable unless it is manually instantiated
// separately). When the preceding line is included, all the compilers I
// tested this on, including gcc, behave exactly the same (throwing a link
// error if the specialization of SomeFunc<int>() is not instantiated
// separately), regardless of whether or not the following line is included;
// however, my understanding is that nothing in the standard requires that
// behavior if the following line is NOT included.
extern template void classA::SomeFunc<int>();
}
fileA.C:
#include "fileA.h"
template <> void myNamespace::classA::SomeFunc<int>() { ... }
Brandon: that's what I thought - the specialized function should never be called. Which is true for the second application I mentioned. The first app, however, clearly calls the specialized form even though the specialization is not declared in the header file!
I mainly seek enlightenment here :-) because the first app is a unit test, and it's unfortunate to have a bug that doesn't appear in the test but in the real app...
(PS: I have fixed this specific bug, indeed by declaring the specialization in the header; but what other similar bugs might still be hidden?)
#[anthony-williams],
are you sure you're not confusing extern template declarations with extern template instantiations? From what I see, extern template may only be used for explicit instantiation, not for specialization (which implies implicit instantiation). [temp.expl.spec] doesn't mention the extern keyword:
explicit-specialization:
template < > declaration
Unless the specialized template function is also listed in the header file, the other application will have no knowledge of the specialized version. The solution is the add SomeFunc<int>() to the header as well.