gcc does not find template specialization - c++

My network code uses template specialization to serialize types that can not simply be copied. I defined a general template
template<typename T> struct TypeHandler
that handles all types that can be transported by a simple memcpy and then I define specializations for all other types. The problem now is that I have a file with multiple such specializations and if I compile the code with Visual Studio everything works fine. But with gcc all template specializations in that file get used with the exception of
template<> struct TypeHandler<uint32_t>
which variable length encodes the integer to save space.
Namespaces are the same for all TypeHandler versions and they are even in the same file. But for some reason gcc decides to use the generalized version and I don't really know why.
EDIT:
It seems that gcc uses the instantiation of TypeHandler from an other project that this one links against but doesnt have a specialization for uint32_t even so it transmits uint32_t fields. GCC doesnt give me any error though. How can i tell gcc to use the specialization like Visual Studio does ?
EDIT2:
managed to generate an SSCCE http://netload.in/dateiz3R4eTVqi3/src.tar.gz.htm
the bug here is the other way around but well.
EDIT3:
fixed filesize : http://netload.in/dateixP6iOvc6bD/src.zip.htm

Minimized to:
test1.cpp:
#include <iostream>
#include <stdint.h>
template<typename T>
struct TypeHandler
{
void Print() { std::cout << "base" << std::endl; }
};
void test1()
{
std::cout << "p1" << std::endl;
TypeHandler<uint32_t>().Print();
}
test2.cpp:
#include <iostream>
#include <stdint.h>
template<typename T>
struct TypeHandler
{
void Print() { std::cout << "base" << std::endl; }
};
template<>
struct TypeHandler<uint32_t>
{
void Print() { std::cout << "int" << std::endl; }
};
void test2()
{
std::cout << "p2" << std::endl;
TypeHandler<uint32_t>().Print();
}
main.cpp:
void test1();
void test2();
int main(){
test1();
test2();
}
On Windows/MinGW 4.8.2, compiling with g++ test1.cpp test2.cpp main.cpp -o test and running produces
p1
base
p2
base
while using g++ test2.cpp test1.cpp main.cpp -o test produces
p1
int
p2
int
This is a straightforward standard violation causing undefined behavior. You can't explicitly specialize the same template in one translation unit but not the other. The explicit specialization is not visible in test1.cpp, causing the compiler to generate an implicit instantiation from the base template. So you get two TypeHandler<uint32_t> specializations, and in this instance it appears that the linker decided to pick the one from the first object file it saw. From §14.7.3 [temp.expl.spec]/p6 of the standard (emphasis mine):
If a template, a member template or a member of a class template is
explicitly specialized then that specialization shall be declared
before the first use of that specialization that would cause an
implicit instantiation to take place, in every translation unit in
which such a use occurs; no diagnostic is required. If the program
does not provide a definition for an explicit specialization and
either the specialization is used in a way that would cause an
implicit instantiation to take place or the member is a virtual member
function, the program is ill-formed, no diagnostic required. An
implicit instantiation is never generated for an explicit
specialization that is declared but not defined.
Also, obligatory quote of the next paragraph (emphasis mine):
The placement of explicit specialization declarations for function
templates, class templates, member functions of class templates,
static data members of class templates, member classes of class
templates, member enumerations of class templates, member class
templates of class templates, member function templates of class
templates, member functions of member templates of class templates,
member functions of member templates of non-template classes, member
function templates of member classes of class templates, etc., and the
placement of partial specialization declarations of class templates,
member class templates of non-template classes, member class templates
of class templates, etc., can affect whether a program is well-formed
according to the relative positioning of the explicit specialization
declarations and their points of instantiation in the translation unit
as specified above and below. When writing a specialization, be
careful about its location; or to make it compile will be such a trial
as to kindle its self-immolation.

Related

Clang and Gcc disagree on explicit specialization after instantiation

In some code I am reviewing I ran into a case where Clang and Gcc disagree. After looking around awhile I cant seem to figure out who is right.
Disclaimer: I know there is a better Singleton pattern, but this is the one used in the code.
Notes:
gcc 7.4.0 on Ubuntu (No error)
clang 6.0.0 on Ubuntu (Throws error)
Difference appears to exist for all post C++11 ISO versions, but I did not try earlier.
foo.hh
#include "sing.hh"
class Foo {
public:
Foo();
~Foo();
static Foo *getSingleton(){
return singleton<Foo>::instance();
}
};
foo.cc
include "foo.hh"
//removing this line results in the error for clang disappearing
template<> singleton<Foo>::GetInstance singleton<Foo>::instance = nullptr;
int main(){};
sing.hh
template<typename T>
class singleton{
typedef T *(*GetInstance)(void);
public:
static GetInstance instance;
};
Results:
$ clang++ foo.cc
foo.cc:3:56: error: explicit specialization of 'instance' after instantiation
template<> singleton<Foo>::GetInstance singleton<Foo>::instance = nullptr;
^
./foo.hh:10:32: note: implicit instantiation first required here
return singleton<Foo>::instance();
^
1 error generated.
$ g++ foo.cc <- No Errors
Neither compiler is technically wrong. The code is invalid, but C++ implementations are not required to give a diagnostic message about this type of error.
Standard [temp.expl.spec]/6 says (emphasis mine):
If a template, a member template or a member of a class template is explicitly specialized then that specialization shall be declared before the first use of that specialization that would cause an implicit instantiation to take place, in every translation unit in which such a use occurs; no diagnostic is required.
You can fix this by declaring the explicit specialization immediately after the definition of singleton in sing.hh:
struct Foo;
template<> singleton<Foo>::GetInstance singleton<Foo>::instance;
Or, if you want all specializations to initialize as null pointers, you can just define the member of the general class template, again probably in sing.hh. Then there's no need for explicit specializations, unless you want a different initializer for some certain type(s).
template<typename T>
typename singleton<T>::GetInstance singleton<T>::instance = nullptr;
From this answer here and the cpp-reference here.
Explicit specialization may be declared in any scope where its primary
template may be defined [...].
Explicit specialization has to appear after the non-specialized
template declaration.
Specialization must be declared before the first use that would cause
implicit instantiation, in every translation unit where such use
occurs
If the explicit specialization was in the sing.cpp file, then neither compiler would complain. Alternatively, you can use forward declaration to do the following and both clang and gcc would be happy.
#include <iostream>
template<typename T>
struct singleton
{
typedef T *(*GetInstance)(void);
static GetInstance instance;
};
template<>
singleton<struct Foo>::GetInstance singleton<struct Foo>::instance = nullptr;
struct Foo
{
static Foo *getSingleton()
{
return singleton<Foo>::instance();
}
};
int main()
{
}
Online code example: https://rextester.com/SPZLS83155

"Destructor already defined" with a specialized destructor

I am experimenting with specialized destructors. This code is perfectly valid and compiles just fine:
#include <iostream>
using namespace std;
template <typename T>
class Cat
{
public:
~Cat();
};
template <typename T>
Cat<T>::~Cat()
{
std::cout << "T" << std::endl;
}
template <>
Cat<int>::~Cat()
{
std::cout << "int" << std::endl;
}
int main()
{
Cat<int> c1;
Cat<float> c2;
return 0;
}
However if I put the class and the destructors in a separate file "Cat.h" and do #include "Cat.h" in Main.cpp, I'm getting a linker error: LNK2005 "public: __thiscall Cat<int>::~Cat<int>(void)" (??1?$Cat#H##QAE#XZ) already defined in Cat.obj. Why?
It sounds like you have the following:
template <>
Cat<int>::~Cat()
{
std::cout << "int" << std::endl;
}
in a header file that is included in two translation units. An explicit specialization of a function template is a non-inline function (C++14 [temp.expl.spec]/12); so this is an ODR violation.
It's the same error you'd get if you implemented a non-template member function (or a free function) in the same place: both translation units end up with a copy of the function, which is not allowed even if the two copies are identical.
To fix this, put the keyword inline before template<>.
There was some discussion in comments about the legality of providing an explicit specialization for a member function of a class template. I believe this is correct, with restrictions according to C++14 [temp.expl.spec]/6:
If a template, a member template or a member of a class template is explicitly specialized then that specialization shall be declared before the first use of that specialization that would cause an implicit instantiation to take place, in every translation unit in which such a use occurs; no diagnostic is required. If the program does not provide a definition for an explicit specialization and either the specialization is used in a way that would cause an implicit instantiation to take place or the member is a virtual member function, the
program is ill-formed, no diagnostic required.
Also, section 7:
The placement of explicit specialization declarations for function templates, class templates, variable templates, member functions of class templates, static data members of class templates, member classes of class templates, member enumerations of class templates, member class templates of class templates, member function templates of class templates, static data member templates of class templates, member functions of member templates of class templates, member functions of member templates of non-template classes, static data member templates of non-template classes, member function templates of member classes of class templates, etc., and the placement of partial specialization declarations of class templates, variable templates, member class templates of non-template classes, static data member templates of non-template classes, member class templates of class templates, etc., can affect whether a program is well-formed according to the relative positioning of the explicit specialization declarations and their points of instantiation in the translation unit as specified above and below. When writing a specialization, be careful about its
location; or to make it compile will be such a trial as to kindle its self-immolation.
In your program it is in the perfect location: immediately after the class definition. The risky sitautions occur when the class might have been instantiated before a declaration at least of the specialization was encountered.
Chances are your Cat.cpp and main.cpp translation units both include the same Cat.h header file. Put your entire template class in a header file, remove the Cat.cpp translation unit and compile without it.
Live example
More details in this SO post:
Why can templates only be implemented in the header file?.

No generated code for explicitly specialized template even with explicit instantiation

I'm getting consistent behavior from both gcc 4.8.3 and clang 3.2, but do not understand why it is happening. Despite the fact that I have an explicit instantiation for a class template, the code is not being generated and I get an undefined symbol when I am using a fully specialized instance of the template.
I have a simple class template definition in a file 'temp.hpp'
#pragma once
template <typename T1>
class C
{
public:
C (T1 c) : d_c(c) {};
~C () = default;
void print ();
private:
T1 d_c;
};
Note that the method 'print()' is declared, but not defined here. I want the definition in the .cpp file and it will be specialized for different types.
So in the temp.cpp file I have the default definition of the print() method
#include "temp.hpp"
#include <iostream>
template<typename T1>
void
C<T1>::print ()
{
std::cout << "Printing: " << d_c << std::endl;
}
followed by a specialization of the class for the type 'float':
template <>
class C <float>
{
public:
C (float f) : d_f(f) {};
~C () = default;
void print ()
{
std::cout << "float: " << d_f << std::endl;
}
private:
float d_f;
};
and since the definitions are in the .cpp file I must explicitly instantiate all the specializations that I will be using. So I have:
template class C<int>;
template class C<float>;
The driver for my test looks like this in test.cpp:
#include "temp.hpp"
int main()
{
int i = 1;
C<int> c_int(i);
float f = 1.2;
C<float> c_float(f);
c_int.print();
c_float.print();
}
Upon compiling and linking this I get error:
test.cpp: undefined reference to `C<float>::print()'
The object code for the C< int > is properly generated. I can see it using nm:
nm -C temp.o
...
0000000000000000 W C<int>::print()
0000000000000000 W C<int>::C(int)
0000000000000000 W C<int>::C(int)
...
As I mentioned earlier, this is consistent with gcc and clang so I'm assuming there is some language rule I don't understand here.
Note that if I add a usage of the print() method in file temp.cpp, then the code is generated, but that is silly and in my real code would be impossible. For this simple test case it would look like:
void foo ()
{
C<float> s(1.3);
s.print();
}
In the real code which motivated this little test my template has 3 template arguments which combine to expand into about 30 permutations of the code. There are one or two of those for which I need a specialization which does something different, but the other 28 I can leave alone.
Any pointers on where I've gone wrong or a language reference for why the explicit instantiation of should not generate code are greatly appreciated. I've spent 1/2 a day reading all the other stackoverflow posts on explicit instantiation and believe I am using it correctly.
From [temp.expl.spec]:
If a template, a member template or a member of a class template is explicitly specialized then that specialization
shall be declared before the first use of that specialization that would cause an implicit instantiation
to take place, in every translation unit in which such a use occurs; no diagnostic is required. If the program
does not provide a definition for an explicit specialization and either the specialization is used in a way
that would cause an implicit instantiation to take place or the member is a virtual member function, the
program is ill-formed, no diagnostic required.
We're explicitly specializing C in temp.cpp, but in test.cpp, it is not declared before it is used. Thus, your code is ill-formed, no diagnostic required. You'll have to simply move the declaration of C<float> into temp.hpp
Always be careful with explicit specializations. The standard takes them very seriously:
The placement of explicit specialization declarations for function templates, class templates, [...], can affect whether a program is well-formed according
to the relative positioning of the explicit specialization declarations and their points of instantiation
in the translation unit as specified above and below. When writing a specialization, be careful about its
location; or to make it compile will be such a trial as to kindle its self-immolation.

Why are some functions within my template class not getting compiled?

I am using VS Express 2013 trying to compile a c++ project. I've created a template class with some functions. The class and its functions are all in one header file. I've included the file, I've used the class, I've called functions from it, and despite all that visual studio won't compile the classes' functions that I'm not using. I've turned off all optimizations. Do I HAVE to use a function that I've written just to see that it compiles or not?
Here is the function:
void remove(ID id)
{
sdfgsdfg456456456456sfdsdf
}
The function shouldn't compile. And indeed the project won't compile if I do use this function, but if I don't use the function the project will compile, even if I use other functions from within this class.
Is there a fix to this? Will the same thing happen if I implement the function in a .cpp file?
Edit: I neglected to mention it is a template class. I've added that information in.
As revealed in comments, the reason this is happening is because remove() is a function in a class template. The compiler only instantiates template code if it is actually used; if you don't call remove(), it can have all the syntax errors you want and nobody will complain.
More formally, § 14.7.1 of the standard states (emphasis mine):
The implicit instantiation of a class template specialization causes
the implicit instantiation of the declarations, but not the
definitions or default arguments, of the class member functions
And later in the same section:
An implementation shall not implicitly instantiate a function
template, a member template, a non-virtual member function, a member
class, or a static data member of a class template that does not
require instantiation.
(the word "implicit" is key here; if you use explicit template instantiation, the compiler will immediately try to instantiate all members using the indicated type(s) and fail if any doesn't compile)
This is not just an optimization; you can exploit this behavior to instantiate class templates with types that only support a subset of the template's operations. For example, suppose you write a template class that will be used with types that support a bar() operation, and in addition, some will also support baz(). You could do this:
template<typename T>
class Foo
{
private:
T _myT;
public:
void bar()
{
_myT.bar();
}
void baz()
{
_myT.baz();
}
};
Now suppose you have these too:
struct BarAndBaz
{
void bar() {}
void baz() {}
};
struct BarOnly
{
void bar() {}
};
This will compile and run just fine:
void f()
{
Foo<BarAndBaz> foo1;
foo1.bar();
foo1.baz();
Foo<BarOnly> foo2;
foo2.bar();
// don't try foo2.baz()!
// or template class Foo<BarOnly>!
}

Template instantiation details of GCC and MS compilers

Could anyone provide a comparison or specific details of how is template instantiation
handled at compile and/or link time in GCC and MS compilers? Is this process different
in the context of static libraries, shared libraries and executables?
I found this doc about how GCC handles it but I'm not sure if the information
is still referring to the current state of things. Should I use the flags
they suggest there when compiling my libraries e.g. -fno-implicit-templates?
What I know (might not necessarily be correct) is that:
templates will be instantiated when actually used
templates will be instantiated as a result of explicit instantiations
duplicate instantiation is usually handled by folding duplicate instantiations, or by deferring instantiation until link time
Point of instantiation
templates will be instantiated when actually used
Not exactly, but roughly. The precise point of instantiation is a bit subtle, and I delegate you over to the section named Point of instantiation in Vandevoorde's/Josuttis' fine book.
However, compilers do not necessarily implement the POIs correctly: Bug c++/41995: Incorrect point of instantiation for function template
Partial instantiation
templates will be instantiated when actually used
That is partially correct. It is true for function templates, but for class templates, only the member functions that are used are instantiated. The following is well-formed code:
#include <iostream>
template <typename> struct Foo {
void let_me_stay() {
this->is->valid->code. get->off->my->lawn;
}
void fun() { std::cout << "fun()" << std::endl; }
};
int main () {
Foo<void> foo;
foo.fun();
}
let_me_stay() is checked syntactically (and the syntax there is correct), but not semantically (i.e. it is not interpreted).
Two phase lookup
However, only dependent code is interpreted later; clearly, within Foo<>, this is dependent upon the exact template-id with which Foo<> is instantiated, so we postponed error-checking of Foo<>::let_me_alone() until instantiation time.
But if we do not use something that depends on the specific instantiation, the code must be good. Therefore, the following is not well-formed:
$ cat non-dependent.cc
template <typename> struct Foo {
void I_wont_compile() { Mine->is->valid->code. get->off->my->lawn; }
};
int main () {} // note: no single instantiation
Mine is a completely unknown symbol to the compiler, unlike this, for which the compiler could determine it's instance dependency.
The key-point here is that C++ uses a model of two-phase-lookup, where it does checking for non-dependent code in the first phase, and semantic checking for dependent code is done in phase two (and instantiation time) (this is also an often misunderstood or unknown concept, many C++ programmers assume that templates are not parsed at all until instantiation, but that's only myth coming from, ..., Microsoft C++).
Full instantiation of class templates
The definition of Foo<>::let_me_stay() worked because error checking was postponed to later, as for the this pointer, which is dependent. Except when you would have made use of
explicit instantiations
cat > foo.cc
#include <iostream>
template <typename> struct Foo {
void let_me_stay() { this->is->valid->code. get->off->my->lawn; }
void fun() { std::cout << "fun()" << std::endl; }
};
template struct Foo<void>;
int main () {
Foo<void> foo;
foo.fun();
}
g++ foo.cc
error: error: ‘struct Foo<void>’ has no member named ‘is’
Template definitions in different units of translation
When you explicitly instantiate, you instantiate explicitly. And make all symbols visible to the linker, which also means that the template definition may reside in different units of translation:
$ cat A.cc
template <typename> struct Foo {
void fun(); // Note: no definition
};
int main () {
Foo<void>().fun();
}
$ cat B.cc
#include <iostream>
template <typename> struct Foo {
void fun();
};
template <typename T>
void Foo<T>::fun() {
std::cout << "fun!" << std::endl;
} // Note: definition with extern linkage
template struct Foo<void>; // explicit instantiation upon void
$ g++ A.cc B.cc
$ ./a.out
fun!
However, you must explicitly instantiate for all template arguments to be used, otherwise
$ cat A.cc
template <typename> struct Foo {
void fun(); // Note: no definition
};
int main () {
Foo<float>().fun();
}
$ g++ A.cc B.cc
undefined reference to `Foo<float>::fun()'
Small note about two-phase lookup: Whether a compiler actually implements two-phase lookup is not dictated by the standard. To be conformant, however, it should work as if it did (just like addition or multiplication do not necessarily have to be performed using addition or multiplication CPU instructions.
Edit: It turns out that what I wrote below is contrary to the C++ standard. It is true for Visual C++, but false for compilers that use "two-phase name lookup".
As far as I know, what you say is correct. Templates will be instantiated when actually used (including when declared as a member of another type, but not when mentioned in a function declaration (that does not have a body)) or as a result of explicit instantiations.
A problem with templates is that if you use the same template (e.g. vector) in several different compilation units (.cpp files), the compiler repeats the work of instantiating the template in each .cpp file, thus slowing down compilation. IIRC, GCC has some (non-standard?) mechanism that can be used to avoid this (but I don't use GCC). But Visual C++ always repeats this work, unless you use explicit template instantiation in a precompiled header (but even this will slow down your compile, since a larger PCH file takes longer to load.) Afterward, the linker then eliminates the duplicates. Note: a comment below linked to a page which tells us that not all compilers operate this way. Some compilers defer function instantiation until link time, which should be more efficient.
A template is not fully instantiated when it is first used. In particular, functions in the template are not instantiated until they are actually called. You can easily verify this by adding a nonsense function to a template you are actively using:
void Test() { fdsh "s.w" = 6; wtf? }
You won't get an error unless you instantiate the template explicitly, or try to call the function.
I expect static libraries (and object files) will store the object code of all templates that were instantiated. But if your program has a certain static library as a dependency, you can't actually call the template functions that were already instantiated therein, at least not in VC++, which always requires the source code (with function bodies) of a template class in order to call functions in it.
I don't think it's possible to call a template function in a shared library (when you don't have the source code of the template function you want to call).