How would the implementation of this function be written?
Good afternoon,
I am working with Boost Graph Library these days and there is a point in an example program that I cannot grasp. It has nothing to do with Boost itself, but with C++ and (basic) template handling.
If I declare the following in an ".h" file it compiles and links without problems.
Code:
template <class Name, class LocMap>
class city_writer {
public:
[...]
template <class Vertex>
void operator()(ostream& out, const Vertex& v) const {
[...]
}
};
But if I separate the implementation to a ".cpp" file as one would usually do
the following code compiles but fails to link:
Code:
template <class Name, class LocMap>
class city_writer {
public:
[...]
template <class Vertex>
void operator()(ostream& out, const Vertex& v) const;
};
And the implementation,
Code:
template<class Name, class LocMap>
template<class Vertex>
void city_writer<Name, LocMap>::operator()(ostream& out, const Vertex& v) const{
[...]
}
The linker outputs:
Code:
>> Invoking: GCC C++ Linker
>> g++ -o"BGLAstar" ./src/CSysLog.o ./src/ErrorRecord.o ./src/bglastar.o ./src/main.
>> undefined reference to `void city_writer<char const**, location*>::operator()<unsigned
>> int>(std::basic_ostream<char, std::char_traits<char> >&, unsigned int const&) const'
So I understand that maybe the correct form is
Code:
template<class Name, class LocMap>
template<class Vertex>
void city_writer<Name, LocMap>::operator()<Vertex>(ostream& out, const Vertex& v) const{
[...]
}
but this generates
Code:
>> g++ -O2 -Wno-deprecated -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"src/bglastar.d" -MT"src/bglastar.d" >> -o"src/bglastar.o" "../src/bglastar.cpp"
>> ../src/bglastar.cpp:26: error: non-template 'operator()' used as template
>> ../src/bglastar.cpp:26: note: use 'city_writer<Name, LocMap>::template operator()' to indicate that it is a
>> template
>> ../src/bglastar.cpp:26: error: expected initializer at end of input
>> make: *** [src/bglastar.o] Error 1
This suggests the following,
Code:
template<class Name, class LocMap>
template<class Vertex>
void city_writer<Name, LocMap>::template operator()(ostream& out, const Vertex& v) const{
[...]
}
but the compiler cannot match it with its use,
Code:
>> /usr/include/boost/graph/graphviz.hpp:256: undefined reference to `void city_writer<char const**,
>> location*>::operator()<unsigned int>(std::basic_ostream<char, std::char_traits<char> >&, unsigned int const&)
>> const'
>> collect2: ld returned 1 exit status
I looked for some theory on how to use templates in my C++ book (Herbert Schmidt) but to no success; this seems to be a problem well ahead of the level of this book.
Any concrete idea? Any suggestion about where can I find a more advanced book on these C++ topics?
Many thanks in advance.
Re: How would the implementation of this function be written?
Templates are only converted to symbols when they're instantiated. That means you typically have to put them entirely in header files (or files #included from header files rather than compiled separately).
One alternative is, if you know every possible instantiation you're going to use, you could explicitly declare in the cpp file where the template is defined what those instantiations are going to be.
Re: How would the implementation of this function be written?
Quote:
But if I separate the implementation to a ".cpp" file as one would usually do
Not for templates.
Template implementations should live solely in the .h file.
(There was an attempt to allow the declaration & definition to live in separate h & cpp files, but only one compiler supports it. The others have no plans to adopt that part of the standard as far as I know)
Re: How would the implementation of this function be written?
Gentlemen, I am gratefull to you for I shall no more have this puzzled expression on my face.