I have a Painter
template class with paint()
template function. I am using tagging to specialize template function inside template class.
I have placed definition of template function paint()
inside Painter.h
and overloaded function inside Painter.cpp
.
I get compiler error when I explicitly instantiate paint()
in Painter.cpp
. My requirement is that I need the implementation of overloaded function paint(ColorTag<Color::RED>)
in the file Painter.cpp.
Source files are as follows:
Painter.h
#include <iostream>
enum class Color {
RED = 0,
GREEN = 1,
BLUE = 2
};
template<Color>
struct ColorTag {
};
template<typename T>
class Painter {
public:
template<Color MyColor>
void paint(ColorTag<MyColor>);
void paint(ColorTag<Color::RED>);
};
template<typename T>
template<Color MyColor>
void Painter<T>::paint(ColorTag<MyColor>){
std::cout << "General" << std::endl;
}
Painter.cpp
#include "Painter.h"
template<typename T>
void Painter<T>::paint(ColorTag<Color::RED>){
std::cout << "RED" << std::endl;
}
template void Painter<int>::paint(ColorTag<Color::RED>);
Main.cpp
#include "Painter.h"
int main(){
Painter<int> painter;
painter.paint(ColorTag<Color::RED>());
return 0;
}
Compiled using
g++ Main.cpp Painter.cpp -std=c++11
I get following compiler error when I explicitly instantiate paint()
in Painter.cpp
Painter.cpp:8:15: error: ambiguous template specialization ‘paint<>’ for ‘void Painter<int>::paint(ColorTag<(Color)0>)’
template void Painter<int>::paint(ColorTag<Color::RED>);
^
Painter.cpp:4:6: note: candidates are: void Painter<T>::paint(ColorTag<(Color)0>) [with T = int]
void Painter<T>::paint(ColorTag<Color::RED>){
^
In file included from Painter.cpp:1:0:
Painter.h:20:10: note: template<Color MyColor> void Painter<T>::paint(ColorTag<MyColor>) [with Color MyColor = MyColor; T = int]
void paint(ColorTag<MyColor>);
What I have tried
Firstly I created a template function called instantiatePaint()
to call paint()
function. Then I placed and instantiated it in Painter.cpp
file. This worked. But this kind of feels awkward.
template<typename T>
template<Color MyColor>
void Painter<T>::instantiatePaint(ColorTag<MyColor>){
paint(ColorTag<MyColor>());
}
template void Painter<int>::instantiatePaint(ColorTag<Color::RED>);
Secondly moved overloaded function definition from Painter.cpp
to Painter.h
. This works but breaks my requirement of having overloaded function paint(ColorTag<Color::RED>)
in Painter.cpp
.
Are there any better methods to fix the problem or what exactly is causing the ambiguity?