I have the following class:
#pragma once
#include <string>
#include <iostream>
class testclass
{
public:
template <class T> T item(const std::string& key)
{
std::cout << "non-specialized\n";
return T();
}
};
For the item method I would like to provide a specialization for strings. I try to do this the following way (in testclass.cpp):
#include "testclass.h"
#include <iostream>
template<> std::string testclass::item(const std::string& key)
{
std::cout << "specialized\n";
return std::reverse(key.begin(), key.end());
}
And then I try to call the function like this:
#include <iostream>
#include "testclass.h"
int main()
{
testclass t;
std::string key = "foo";
t.item<int>(key);
std::string s = t.item<std::string>(key);
std::cout << s << std::endl;
}
However, the output is
$ ./a.out
non-specialized
non-specialized
(empty line)
What I excepted was
$ ./a.out
non-specialized
specialized
oof
How can I do this properly? I am using g++ 4.5.2 to compile the program.
Edit:
The solution is the move the whole definition of the specialization of item to testclass.h (but not into the class). I had other mistakes in the program, such as not including <algorithm> (for reverse), and incorrectly thinking that it would return the reversed string. To achieve the excepted behaviour, the .cpp file is left empty, and the header contents are the following:
#pragma once
#include <string>
#include <iostream>
#include <algorithm>
class testclass
{
public:
template <class T> T item(const std::string& key)
{
std::cout << "non-specialized\n";
return T();
}
};
template<> std::string testclass::item(const std::string& key)
{
std::cout << "specialized\n";
std::string s = key;
std::reverse(s.begin(), s.end());
return s;
}
The problem boils down to the common problem of not having the templates in the header file. The compiler, when processing
maindoes not see the specialization and it generates its own instantiation of the generic template forstd::string. This is a violation of the ODR, as there are now 2 different specializations forstd::stringin the same program, but the compiler is not required to diagnose it.The simple solution is to declare/define the specialization in the header so that the compiler can either use it, or at least will know not to generate the specialization from the generic version when processing
main