2016-04-29 3 views
0

У меня есть Painter шаблон класс с paint() шаблон функции. Я использую теги, чтобы специализировать функцию шаблона внутри класса шаблона. Я разместил определение функции шаблона paint() внутри Painter.h и перегруженной функции внутри Painter.cpp.Неоднозначный шаблон специализации

Я получаю ошибку компилятора, когда я явно создаю экземпляр paint() в Painter.cpp. Мое требование в том, что мне нужна реализация перегруженной функции paint(ColorTag<Color::RED>) в файле Painter.cpp.

Исходные файлы следующим образом:

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

То, что я пытался

Во-первых I создал шаблон functio 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.cpp к Painter.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>); 

С помощью этого синтаксиса, и г ++ и лязга скомпилируйте код. 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 )' не является специализацией шаблона, это 'перегруженная' функция. Во-вторых, я не знаю, понимаю ли я, что вы хотите, anywat, это то, что вы имели в виду: http://ideone.com/euoiPN – PcAF

+0

Да, функции шаблона не могут быть специализированы внутри класса шаблонов. Но то, что сделали с помощью меток, дает мне эффект специализации псевдо-шаблонов. ** Мое требование состоит в том, что мне нужна специализированная (помеченная) функция в самом файле Painter.cpp. **. Вы можете увидеть ** Мои попытки исправить **, если вы читаете в конце моего вопроса. Как я уже сказал в моих попытках исправить **, проблемы решаются легко, если я просто переношу псевдоспециализированную функцию на «Painter.h» без каких-либо _специфических экземпляров в «Painter.cpp». – Vivek

Смежные вопросы