2016-04-29 149 views
0

我有一个Painter模板类与paint()模板功能。我正在使用标记专门化模板类中的模板函数。 我已经将Painter.h中的模板函数paint()的定义和Painter.cpp中的函数重载。暧昧模板专业化

当我在Painter.cpp中明确实例化paint()时,出现编译器错误。 我的要求是我需要在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 

我获得以下编译器错误,当我明确实例paint()在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>); 

我已经试过

首先我创建了一个模板函数n调用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.cppPainter.h。这工作,但打破了我的要求paint(ColorTag<Color::RED>)Painter.cpp超载功能。

有没有更好的方法来解决这个问题,究竟是什么导致了模糊性?

回答

-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的

+1

请你回答,你都非常相信,这将100%的工作,“不知道”使得冒险 – piyushj

+0

因为我没有检查它GCC,我读的地方双模板是编译器相关的。 – Jai

0

你想要的是与T = int所以正确的语法明确的分工是:

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

有了这个语法,无论是g ++以及铛编译代码。 Live example

0

为什么你不能初始化整个类而不是函数?

template class Painter<int>; 
+0

这工作,直到它休息。有时我们不能明确地实例化整个模板类。可以说,我们有两个结构可以替代'int'。 'struct box {static void foo(){std :: cout <<“foo”;}};''struct Cube {static void bar(){std :: cout <<“Cube”;}};'。使模板函数'paint(ColorTag )'调用'T :: bar()'和专用函数来调用'T :: foo()'。现在尝试使用“Box”或“Cube”实例化完整的类。 – Vivek

+0

首先注意,在你的代码'paint(ColorTag )'中不是模板特化,它是'overloaded'函数。其次,我不知道我是否清楚地理解你想要什么,但是这是你的意思:http://ideone.com/euoiPN – PcAF

+0

是的模板函数不能在模板类中专用。但是使用标签做了什么,这让我看到了伪模板专门化的效果。 **我的要求是我需要Painter.cpp文件本身的专用(标记)功能。**。你可以看到**我试图修复**,如果你阅读我的问题结束。正如我在**中说过的,我试图修复**,如果我在'Painter.cpp'中没有任何_explicit实例化的情况下将伪专用函数移动到'Painter.h',就可以轻松解决问题。 – Vivek