模糊的模板专业化

时间:2016-04-29 06:46:47

标签: c++ templates

我有一个带有Painter模板功能的paint()模板类。我正在使用标记来专门化模板类中的模板函数。 我在paint()中放置了模板函数Painter.h的定义,在Painter.cpp中放置了重载函数。

我在paint()中显式实例化Painter.cpp时出现编译错误。 我的要求是我需要在Painter.cpp文件中实现重载函数paint(ColorTag<Color::RED>)

源文件如下:

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;
}

使用

编译
g++ Main.cpp Painter.cpp -std=c++11

当我在Painter.cpp

中显式实例化paint()时,我得到以下编译器错误
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>);

我尝试了什么

首先我创建了一个名为instantiatePaint()的模板函数来调用paint()函数。然后我放置并在Painter.cpp文件中实例化它。这很有效。但这种感觉很尴尬。

template<typename T>
template<Color MyColor>
void Painter<T>::instantiatePaint(ColorTag<MyColor>){
    paint(ColorTag<MyColor>());
}

template void Painter<int>::instantiatePaint(ColorTag<Color::RED>);

其次将重载的函数定义从Painter.cpp移至Painter.h。这有效但却违反了我在paint(ColorTag<Color::RED>)中重载函数Painter.cpp的要求。

有没有更好的方法来解决问题或究竟是什么导致歧义?

3 个答案:

答案 0 :(得分:0)

你想要的是T = int的明确专业化,所以正确的语法是:

template<> 
void Painter<int>::paint(ColorTag<Color::RED>);

使用这种语法,g ++和clang都会编译代码。 Live example

答案 1 :(得分:0)

为什么不能初始化全班而不是函数?

template class Painter<int>;

答案 2 :(得分:-1)

#include <iostream>

enum Color {
    RED = 0,
    GREEN = 1,
    BLUE = 2
};

template<Color color = Color::RED>
struct ColorTag 
{
    // your Implementation
};

template<>
struct ColorTag <Color::RED>
{
    // your Implementation specific to Color::RED
};

template<typename T>
class Painter {
public:

    // template specialization can not apply on method level
    // use class or struct
    template<Color MyColor> 
    void paint(ColorTag<MyColor>);
};

template<typename T>
template<Color MyColor>
void Painter<T>::paint(ColorTag<MyColor> colorTag)
{
    std::cout << "General"<<std::endl;
}

在Visual Studio 2012上正常工作,不确定Gcc