问题
I have a template class "Extra," defined in "extra.h," with a function "doSomething," and I have defined two specializations of "doSomething." Two different functions create objects of type "Extra," each with a different type parameter, and each calls a different one of the specializations. The two client functions, "client1" and "client2," are defined in two files, "client1.cpp" and "client2.cpp," respectively. In a third file, "main" calls "client1" and then "client2." Now, "client1.cpp" and "client2.cpp" both #include "extra.h." I get a linker error that "doSomething" has (2) multiple definitions. Naturally, if I put the defintions of "client1" and "client2" into a single source file, I do not have this problem. Is there any way that I can preserve my arrangement of distinct files for "client1" and "client2"? Below is my code. Thank you!
// extra.h
#ifndef EXTRA_H
#define EXTRA_H
template <typename T>
class Extra
{
public:
Extra(T);
~Extra();
T doSomething(T);
private:
Extra() {}
T m_value;
};
template <typename T> Extra<T>::Extra(T input) : m_value{input} {}
template <typename T> Extra<T>::~Extra() {}
template <> int Extra<int>::doSomething(int input)
{
return input * m_value;
}
template <> double Extra<double>::doSomething(double input)
{
return input + m_value;
}
template <typename T> T Extra<T>::doSomething(T input)
{
return input;
}
#endif
// client1.cpp
#include "extra.h"
#include <iostream>
void client1()
{
std::cout << "In client1." << std::endl;
Extra<int> extra(2);
int res = extra.doSomething(3);
std::cout << "Value: " << res << std::endl;
}
// client2.cpp
#include "extra.h"
#include <iostream>
void client2()
{
std::cout << "In client2." << std::endl;
Extra<double> extra(2.0);
double res = extra.doSomething(2.0);
std::cout << "Value: " << res << std::endl;
}
// main.cpp
#include <iostream>
void client1();
void client2();
int main()
{
std::cout << "In main." << std::endl;
client1();
client2();
return 0;
}
And here, for completness, is my linker error:
$ g++ -std=c++11 -o client client1.cpp client2.cpp main.cpp
duplicate symbol __ZN5ExtraIiE11doSomethingEi in:
/var/folders/mf/jdvfkpms609206zpz8x5237r0000gn/T/client1-6fa7ed.o
/var/folders/mf/jdvfkpms609206zpz8x5237r0000gn/T/client2-387444.o
duplicate symbol __ZN5ExtraIdE11doSomethingEd in:
/var/folders/mf/jdvfkpms609206zpz8x5237r0000gn/T/client1-6fa7ed.o
/var/folders/mf/jdvfkpms609206zpz8x5237r0000gn/T/client2-387444.o
ld: 2 duplicate symbols for architecture x86_64
回答1:
You need to mark your doSomething
inline:
template <> inline int Extra<int>::doSomething(int input)
{
return input * m_value;
}
template <> inline double Extra<double>::doSomething(double input)
{
return input + m_value;
}
来源:https://stackoverflow.com/questions/44081844/c-template-specialization-definitions-shared-across-files