Undefined symbol on a template operator overloading function - c++

I have this function declaration:
template<class T>
a::A& a::A::operator<<(T out) {
std::cout << out;
return (*this);
}
and this function definition:
namespace a {
...
class A {
...
template<class T> A& operator<<(T);
And I call it as:
a::A b;
b << 1;
and this is the Makefile:
app: main.o A.o
g++ main.o A.o -o app
main.o: main.cpp
g++ -c main.cpp
A.o: A.cpp
g++ -c A.cpp
and it gives me:
Undefined symbols: a::A& a::A::operator<< <int>(int)
why is that?

The function template will be turned into an actual function at compile time, once the type represented by T (that is, int in your case) is actually known. However, this is not the case before main.cpp is compiled. At the time when A.cpp is compiled, the template function is not instantiated into an actual function, therefore the object file generated doesn't include the binary version of the function.
There are two ways to solve this.
Include the function definition in your header file. That is, make
template<class T>
a::A& a::A::operator<<(T out) {
std::cout << out;
return (*this);
}
a part of the header file, and remove the function definition from the .cpp file.
The effect of this is that any .cpp file that includes this header will be able to use any instantiation of the template, i.e. for any value of T.
Alternatively, include an explicit template instantiation statement in A.cpp:
template a::A& a::A::operator<<(int out);
This will cause the compiler to actually instantiate the template when A.cpp is compiled, and to include the compiled function in the object file. Hence the linker can find it when linking main.o and A.o together, and all is fine. The disadvantage is that it will only work for the specific types (in this case, only int) that you provided explicit instantiations for.

Try changing your definition to:
template<class T>
a::A& a::A::operator<< <T> (T out) {
std::cout << out;
return (*this);
}
?
(Make sure it's in the header file)

Related

Linking multiple files with template class in another .cpp file

I am learning template programming and have come across an error i cannot understand. My task involves 3 files
1) A main File (with main function)
#include<iostream>
#include "templates.h"
int main(){
trial <int>x;
x.input(3);
std::cout<<x.ret();
return 0;
}
2) A header File
#ifndef templ
#define templ
template<typename T>
class trial{
T val;
public:
void input(T x);
T ret();
};
#include "templateref.cpp"
#endif
3) A .cpp file used define the functions of class trial
#ifndef templ
#define templ
#include"templates.h"
#endif
template<class T>
void trial<T>::input(T x){
val = x;
return ;
}
template<class T>
T trial<T>::ret(){
return val;
}
As i undestand from here "Undefined reference to" template class constructor and https://www.codeproject.com/Articles/48575/How-to-define-a-template-class-in-a-h-file-and-imp i had to instantiate the template class for it to work.
My problem occurs when I try to compile it.
when I do
clang++ templates.cpp templateref.cpp -Wall -o template
I get the error
templateref.cpp:14:6: error: variable has incomplete type 'void'
void trial<T>::input(T x){
^
templateref.cpp:14:11: error: expected ';' at end of declaration
void trial<T>::input(T x){
^
;
templateref.cpp:14:11: error: expected unqualified-id
templateref.cpp:20:11: error: qualified name refers into a specialization of variable template 'trial'
T trial<T>::ret(){
~~~~~~~~^
templateref.cpp:14:6: note: variable template 'trial' declared here
void trial<T>::input(T x){
^
4 errors generated.
This is fixed by
clang++ templates.cpp -Wall -o template
the compilation runs without errors and gives results as expected .
So my question is (sorry for the long explanation , as i couldnt explain my question in shorter words) why cant I link these files together and what am i missing?
You shouldn't compile the member definition file – it's already included in the header.
Due to the include guard in that file, the entire header is excluded when the compiler processes it, and the class template definition doesn't exist.
Just compile the main file.

Operator overloading clang++ and g++ different output

With this sample program I observe a different behavior in g++ and clang
Foo.h:
#include <iostream>
namespace Bar
{
class Foo
{
public:
Foo(int x) : _x(x)
{}
int x() const
{
return _x;
}
private:
int _x;
};
}
std::ostream& operator <<(std::ostream& os, const Bar::Foo* foo);
Foo.cpp
#include <Foo.h>
using namespace std;
ostream& operator <<(ostream& os, const Bar::Foo* foo)
{
return os << foo->x();
}
main.cpp
#include <iostream>
using namespace std;
template<typename T>
void print(const T& t)
{
cout << t << endl;
}
#include <Foo.h>
int main(int argc, char** argv)
{
Bar::Foo* foo = new Bar::Foo(5);
print(foo);
}
Compiling with clang++ and g++ produce different results:
air:~ jose$ clang++ Foo.cpp main.cpp -I.
air:~ jose$ ./a.out
0x7ff9e84000e0
air:~ jose$ g++ Foo.cpp main.cpp -I.
air:~ jose$ ./a.out
5
Which one is correct and why?.
In this particular case, clang++ is correct.
The problem is how lookup is performed inside the template print. In the expression inside print the call to operator<< is dependent. Name resolution for dependent names is handled in 14.6.4:
In resolving dependent names, names from the following sources are considered:
— Declarations that are visible at the point of definition of the template.
— Declarations from namespaces associated with the types of the function arguments both from the instantiation context (14.6.4.1) and from the definition context.
In your case, the declaration of your operator is not visible at the point of definition of the template, since the header is included afterwards, and it does not live in any of the associated namespaces of the function arguments (namely ::std for ::std::ostream and ::Bar for ::Bar::Foo*), so it won't be found.
Now, there is an overload in ::std that takes a void*, and that will be found by Argument Dependent Lookup. The ::Bar::Foo* will be converted to a void* and the address will be printed.
That is, in a standard compliant compiler.
I forgot to add this here, and left it only in the comment, but it is important enough:
Always define the operators that apply to your types in the same namespace that holds the types on which they apply. Let Argument Dependent Lookup do it's magic for you. It was specifically designed to serve this particular purpose, use it.

What is a robust way of template specialization in C++ for separated header/source

In moderate-sized or even big complex projects separating template declaration and definition is useful
to reduce compilation time.
However, in a complex code small programmer mistakes may lead to unnoticed behaviour change,
e.g. a generic version is called instead of a specialization.
Example:
Template specialization became invisible due to a missed declaration.
///////////////////// file A.hpp /////////////////////
#include <iostream>
template <typename T>
class A
{
public:
void foo()
{
std::cerr << " calling generic foo " << std::endl ;
}
};
// forgetting following declaration leads to an unintended program behaviour
template <> void A< int >::foo();
///////////////////// file A-foo-int.cpp /////////////////////
#include "A.hpp"
template <>
void A< int >::foo()
{
std::cerr << "calling <int> version of foo" << std::endl;
}
///////////////////// file main.cpp /////////////////////
#include "A.hpp"
int main(int argc , char** argv)
{
A<int>* a = new A<int>();
a->foo();
return 0;
}
///////////////////// Makefile /////////////////////
CC = g++
CPPFLAGS += -Wall -O3
CXXFLAGS += --std=gnu++0x
all: nonrobust-template-setup
nonrobust-template-setup: main.o A-foo-int.o
$(CC) $(CPPFLAGS) main.o A-foo-int.o -o nonrobust-template-setup
clean:
rm -rf *.o nonrobust-template-setup
//////////////////////////////////////////
Question:
is a more robust setup possible (compiler- and platform-independent)
and if, how would it look like?
If not, what is a good way to test that a desired function version is called?
You cannot separate declarations and definitions that way: if you relegate the definition of your specialized member functions in a separate .cpp file, no matter if you declare your specialization immediately after the primary template, the compiler won't be able to instantiate it, and the linker will complain about unresolved references.
Normally, the definition of member functions of a class template goes in a header file, unless you provide an explicit instantiation for the corresponding class templates:
template class X<int>; // You should add this to make your program build,
// or instantiate the corresponding class template
// specialization and invoke the foo() method in the
// same translation unit (A.cpp)
In general, unless you are facing really horrible compilation time issues, I would suggest you to follow the common practice and put everything in a header file to be included by all the translation units that need to use the class template:
///////////////////// file A.hpp /////////////////////
#include <iostream>
template <typename T>
class A
{
public:
void foo()
{
std::cerr << "error: called generic foo " << std::endl ;
}
};
template <>
void A< int >::foo()
{
std::cerr << "calling <int> version of foo" << std::endl;
}
///////////////////// file main.cpp /////////////////////
#include "A.hpp"
int main(int argc , char** argv)
{
A<int>* a = new A<int>();
a->foo();
return 0;
}
If you are facing really horrible compilation time issues, then you could separate the member function definitions and put them into separate translation units with explicit instantiations, but in C++11 there is no clean/easy way to make sure that all the specializations you relegate in separate .cpp files are declared immediately after the primary template (as good practice recommends). If there were, I guess it would be so popular that you wouldn't have needed to come here and ask about it, because everybody faces such a design issue.
In some cases some fancy macros could help, but doubtfully they would bring more benefit than maintenance pain in really complex projects.
A solution to this problem was attempted in the C++03 standard by introducing the export keyword, but implementation experience proved it too hard to support for compiler vendors, which is why export is no more part of the C++ Standard (since C++11).
Hopefully, a better solution for modules will make it into C++14 and provide a solution for template design.
I think the best you can do is to static_assert that the generic template is never instantiated with the types that are supposed to be specialized.
The following code is to illustrate only - I'd probably use BOOST_STATIC_ASSERT (and std::is_same if I could use c++11). The basic idea is to prevent implicitly instantiating the non-specialized template with the set of types you forbid. Of course if you forget to add the static assert AND the specialization you're still going to fail.
template<class T, class U>
struct is_same { enum { value = false }; };
template<class T>
struct is_same<T, T> { enum { value = true }; };
template <bool enable>
struct StaticAsserter
{
char test[enable];
};
template <typename T>
struct foo
{
// Make sure we can't implicit instantiate foo for int.
StaticAsserter<!is_same<int, T>::value> DisallowInt;
};
int main()
{
foo<unsigned> hi;
foo<int> fail;
return 0;
}
The way to be sure of this is to not provide any definition of the generic template's foo(). There's no need to declare specializations when you're doing it this way:
// A.h
template <typename T> struct A { void foo(); };
// main.cc
#include "A.h"
int main ( int c, char **v )
{
A<int>().foo();
// A<long>().foo(); // this line will compile but not link
}
// A.cc
#include <cstdio>
#include "A.h"
template<> void A<int>::foo() { puts("foo!"); }
Okay, from comments instantiating the generic A<T>::foo() implementation is not necessarily an error, only if you have supplied a specialization elsewhere.
So what you want is to find generic-template instantiations whose names duplicate specializations that should only have been instantiated in a specific list of compiler object files -- which reduces to looking for matching fields in two datasets. For that, there's join:
# every object and where it's defined
nm -A *.o | c++filt | grep ' T ' \
| sort -k3 > #all.definitions
# definitions that shouldn't be duplicated:
nm -A A-foo-int.o | c++filt | grep ' T ' \
| sort -k3 > #my.definitions
# everything that shows on both lists:
join -j3 #my.definitions #all.definitions
edit: sed syntax for the grep patterns didn't really work very well.

Explicit Specialization of non-template member function is not called

...unless something else from the library is called. Here is a minimal example.
test1.cpp
#include <iostream>
void proofOfTwoLinked();
template <class T>
struct Foo
{
void bar(){ std::cout << "normal bar\n"; }
};
struct A{};
struct B{};
struct C{};
struct D{};
template <> void Foo<B>::bar(){ std::cout << "B bar\n"; }
int main()
{
Foo<A> a;
Foo<B> b;
Foo<C> c;
Foo<D> d;
a.bar();
b.bar();
c.bar();
d.bar();
//proofOfTwoLinked();
}
test2.cpp
#include <iostream>
struct C;
template <class T>
struct Foo
{
void bar(){ std::cout << "normal bar\n"; }
};
template <> void Foo<C>::bar(){ std::cout << "C bar\n"; }
void proofOfTwoLinked()
{
std::cout << "Yup, two is linked\n";
}
If I compile the two together, the program works as expected:
$ rm test; rm *.a; rm *.o; g++ -c test1.cpp; g++ -c test2.cpp; g++ -o test test1.o test2.o; ./test
normal bar
B bar
C bar
normal bar
If I compile test2, put it in an archive, and then link the program against that... the specialization for type C is not executed when c.bar() is called:
$ rm test; rm *.a; rm *.o; g++ -c test1.cpp; g++ -c test2.cpp; ar -r test2.a test2.o; g++ -o test test1.o test2.a; ./test
ar: creating test2.a
normal bar
B bar
normal bar
normal bar
But if I uncomment the last function call of test1 (proofOfTwoLinked) and then compile again, the specialization is executed.
$ rm test; rm *.a; rm *.o; g++ -c test1.cpp; g++ -c test2.cpp; ar -r test2.a test2.o; g++ -o test test1.o test2.a; ./test
ar: creating test2.a
normal bar
B bar
C bar
normal bar
Yup, two is linked
This strikes me as weird, and is certainly contrary to my expectation. Is this in fact normal behavior? Perhaps since there already exists some form of every function that is called in main() before the linker searches test2.a it skips the archive. Is there a way to force the linker to "look at the whole archive"?
I'm using gcc 4.6.1 and ar 2.21.53 (in ubuntu).
Using MSVC2010SP1 I get slightly different results:
compiling together as is I don't get "C bar". This is as expected because test1.cpp and test2.cpp are separate compilation units and with no forward declarations of the specializations that the other contains test1.cpp will instantiate its the default "normal bar" and test2.cpp will not instantiate the "C bar" because it can't see anything using it.
when I uncomment proofOfTwoLinked(); i get "Yup, two is linked" which is expected because "proofOfTwoLinked()" is forward declaired. I still don't get "C bar" which is as expected because it is not forward declaired in test1.cpp
When I compile again adding
template <> void Foo<C>::bar();
to test1.cpp I get a linker error because although the test1.cpp compilation unit now knows there is a
template <> void Foo<C>::bar()
out there somewhere, test2.cpp still does not know that anyone is using it.
When I compile again adding
template void Foo<C>::bar();
to test2.cpp everything works and I get "C bar". Note that
template void Foo<C>::bar();
must be BEFORE its definition.
As far as I can tell MSVC is acting correctly and gcc is acting weird in your case. I used http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1905.pdf section 14.7 as a reference, it might be helpful.

Templates and separate compilation

I want to write a program in C++ with separate compilation and I wrote this:
main.cpp
#include <iostream>
#include "Stack.h"
using namespace std;
int main(int argc,char* argv[])
{
Stack<int> st;
st.push(1);
return 0;
}
Stack.h
#ifndef _STACK_H
#define _STACK_H
template<typename T>
class Stack
{
private:
struct Node
{
Node* _prev;
T _data;
Node* _next;
};
int _size;
Node* _pos;
public:
Stack();
T pop();
void push(T const &el);
int getSize() const;
};
#endif
Stack.hpp
#include "Stack.h"
#include <malloc.h>
template <typename T>
Stack<T>::Stack()
{
_size = 0;
_pos = (Node*)malloc(sizeof(Node));
_pos->_prev = NULL;
_pos->_next = NULL;
}
template <typename T>
T Stack<T>::pop()
{
if (_size == 0)
return NULL;
T tmp = _pos->_data;
if (_pos->_prev == NULL)
free(_pos);
else
{
_pos->_prev->_next = _pos->_next;
if (_pos->_next != NULL)
{
_pos->_next->_prev = _pos->_prev;
}
free(_pos);
}
_size--;
return tmp;
}
template <typename T>
void Stack<T>::push(T const &el)
{
Node* n = (Node*)malloc(sizeof(Node));
_pos->_next = n;
n->_prev = _pos;
n->_data = *el;
_pos = n;
_size ++;
}
template<typename T>
int Stack<T>::getSize() const {return _size;};
I compiled the program with g++ and I get this error:
ccyDhLTv.o:main.cpp:(.text+0x16): undefin
ed reference to `Stack<int>::Stack()'
ccyDhLTv.o:main.cpp:(.text+0x32): undefin
ed reference to `Stack<int>::push(int const&)'
collect2: ld returned 1 exit status
I know that the problem is because I'm using templates but I do not know how to fix it.
OS - Windows
compilation line - g++ main.cpp Stack.h Stack.hpp -o main.exe
Template classes need to have the method definitions inside the header file.
Move the code you have in the .cpp file inside the header, or create a file called .impl or .imp, move the code there, and include it in the header.
The compiler needs to know the method definitions to generate code for all specializations.
Before you ask, no, there is no way to keep the implementation outside the header.
I would say it will be more pragmatic to first understand how separate compilation works for normal (untempelated) files and then understand how g++ compiler does it for template.
First in normal files, when the header file containing only the declarations are #included in main file, the preprocessor replaces the declarations from the header and puts it to the main file. Then after the preprocessing phase is over, the compiler does one by one compilation of the pure C++ source code contained in .cpp files and translates it into object file. At this point the compiler doesn't mind the missing definitions (of functions/classes) and the object files can refer to symbols that are not defined. The compiler, hence can compile the source code as long as it is well formed.
Then during the linking stage the compiler links several files together and it is during this stage the linker will produce error on missing/duplicate definitions. If the function definition is correctly present in the other file then the linker proceeds and the function called from the main file is successfully linked to the definition and can be used.
For templates, things work differently. It will be illustrative to consider an example, so I pick a simple one:
consider the header file for template array class:
array.h
#ifndef _TEMPLATE_ARRAY_H_
#define _TEMPLATE_ARRAY_H_
template <class T>
class Array
{
private:
T *m_list;
int m_length;
public:
Array() //default constructor
{
m_list = nullptr;
m_length = 0;
}
Array(int length)
{
m_list = new T[length];
m_length = length;
}
~Arrary()
{
delete[] m_list;
m_list = nullptr;
}
//undefined functions
int getLength();
T getElement(const int pos);
};
and the corresponding array.cpp file :
include "array.h"
template <class T>
array<T>::getLength()
{ return m_length; }
template <class T>
T Array<T>::getElement(const int pos)
{ return m_list[pos]; }
Now consider the main file where two instances of the templated object array, one for int and another for double is created.
main.cpp
#include "array.h"
#include <iostream>
int main()
{
Array<int> int_array;
Array<double> double_array;
std::cout << int_array.getLength() <<"\n";
std::cout << double_array.getLength() << "\n";
}
When this piece of code is compiled, the preprocessor first copies the template declarations from the header file to the main file as usual. Because in the main file Array< int > and Array< double > objects are instantiated, compiler instantiates two different definitions of Array class, one each for double and int and then instantiate the Array objects in the main.cpp file.
Note till this point the function definitions for Array< int >::getLength() and Array< double >::getLength() is still missing in the main.cpp file but since the source code is well formed the compiler compiles the main.cpp file without any hassle. In short there's no difference b/w templated object/function compilation and non-templated function compilation till now.
In the meanwhile the code file for array.cpp containing the template function definitions for Array< T >::getLength() and Array< T >::getElement() is compiled, but by this time the compiler would have forgotten that main.cpp needs Array< int >::getLength() and Array< double >::getLength() and would happily compile the code array.cpp without generating any instances for int and double version of the function definition needed by the main.cpp file. (Remember that compiler compiles each file separately!)
It is during the linking phase horrible template errors start popping because of the missing function definitions for int and double version of template function definition that are required by the main file. In the case of non-template declarations and definitions, the programmer makes sure to define the sought function in a file which can be linked together with the file calling the function. But in the case of templates, the linker which executes after the compilation phase, cannot do a task that a compiler is suppose to do, i.e generate a code, in this case for int and double type of the template function
There are ways to get around this
Having gone through the entire story, one can easily conclude that the entire fuss up around template separate compilation is due to linkage (i.e) if all codes are written correctly, class and functions declared in header and defined in another separate file). Ways of getting around this are :
Define the class and functions in the header files themselves rather than in separate file so that the contents of header file when included in the main file, includes the templated definitions which cause appropriate instances of necessary functions to be defined by the compiler.
Instantiate the type definitions you know you will need in the separate file where the template definitions are written. This will then directly be linked to the function calls in the main file.
Another way to get around this is to name the .cpp file where definitions are written to .inl* file (from the e.g drawn above, chagne array.cpp to array.inl); inl means inline and include the .inl file from the bottom of the header file. This yields the same result as defining all functions within the header file but helps keeping the code a little cleaner.
There's another way, i.e #include .cpp file with templated definitions in the main file which I personally don't prefer because of non-standard usage of #include.
It is absolutely possible to have templates and separate compilation, but only if you know in advance for which types the template will be instantiated.
Header file sep_head.h:
template< typename T >
class sep{
public:
sep() {};
void f();
};
Main:
#include "sep_head.h"
int main() {
sep<int> s; s.f();
sep<double> sd; sd.f();
sep<char> sc; sc.f();
return 0;
}
Implementation:
#include "sep_head.h"
template< typename T >
void sep<T>::f() {}
template class sep<int>;
template class sep<double>;
template class sep<char>;