2010-06-16 3 views
99
template<typename T> 
class CConstraint 
{ 
public: 
    CConstraint() 
    { 
    } 

    virtual ~CConstraint() 
    { 
    } 

    template <typename TL> 
    void Verify(int position, int constraints[]) 
    {  
    } 

    template <> 
    void Verify<int>(int, int[]) 
    { 
    } 
}; 

Компиляции это под г ++ дает следующее сообщение об ошибке:Явная специализация в области не-имена сферы

Явной специализации в не-пространстве имен сферы «класса CConstraint»

В VC, он компилирует нормально. Может кто-нибудь, пожалуйста, дайте мне знать обходной путь?

ответ

85

VC++ в этом случае несовместим - явные специализации должны быть в области пространства имен. C++ 03, §14.7.3/2:

An explicit specialization shall be declared in the namespace of which the template is a member, or, for member templates, in the namespace of which the enclosing class or enclosing class template is a member.
An explicit specialization of a member function, member class or static data member of a class template shall be declared in the namespace of which the class template is a member.

Кроме того у вас есть проблема, которую вы не можете специализироваться функции-члены без явного Специализируя содержащего класс из-за C++ 03, § 14.7 .3/3, так что один раствор должен был бы позволить Verify() вперед к, возможно, специализированных, свободная функция:

namespace detail { 
    template <typename TL> void Verify  (int, int[]) {} 
    template <>   void Verify<int>(int, int[]) {} 
} 

template<typename T> class CConstraint { 
    // ... 
    template <typename TL> void Verify(int position, int constraints[]) { 
     detail::Verify<TL>(position, constraints); 
    } 
}; 
+8

* Несоответствие в этом случае *: как всегда :)? Шаблоны и VC++ не так хорошо смешиваются:/ –

+0

Спасибо большое :) – Mark

+5

Это не соответствует требованиям, что позволит вам сделать то, что обычно не разрешает стандарт - что не является проблемой для кода, который с самого начала согласуется (вы пишете такой код, правильно? ~). Реальные проблемы соответствия - это когда он не будет компилировать то, что требуется Стандарту для компиляции, или будет вести себя иначе, чем указано. –

74

Другой способ решить это путем делегирования частной функции и перегрузки этой функции. Таким образом, у вас все еще есть доступ к данным участника *this и к типу параметра внешнего шаблона.

template<typename T> 
struct identity { typedef T type; }; 

template<typename T> 
class CConstraint 
{ 
public: 

    template <typename TL> 
    void Verify(int position, int constraints[]) 
    { 
    Verify(position, constraints, identity<TL>()); 
    } 

private: 
    template<typename TL> 
    void Verify(int, int[], identity<TL>) 
    { 

    } 

    void Verify(int, int[], identity<int>) 
    { 

    } 
}; 
+0

Большое спасибо. Я тоже искал это, так как мне нужно получить доступ к этому. Хотел бы я выбрать 2 ответа. – Mark

+7

Если бы я был вами, я бы выбрал этот ответ. @Johannes: Ваш ответ просто идеален, спасибо. –

+0

Благодарим вас, спасибо, Johannes Schaub, за этот ответ. – Rethunk

1

Вы не можете быть в состоянии явно специализироваться шаблон члена, но вы можете частично специализироваться его. Если вы добавите второй параметр «int dummyParam», а также добавьте его в специализацию, он должен работать с обоими компиляторами.

Не то, чтобы я знал об этом более 10 секунд назад, но искал ту же ошибку, я столкнулся с this link, и это сработало для моей специализации по шаблону участника.

+1

Вы не можете частично специализировать функцию – metamorphosis

4

Еще лучше: вы можете объединить частичную специализацию с аргументами шаблона по умолчанию. Таким образом, модификация кода VC++ незначительна, потому что вызовы специализированной функции не нуждаются в изменении.

template <typename TL, class Dummy=int> 
void Verify(int position, int constraints[]) 
{ 
} 

template <class Dummy=int> 
void Verify<int, Dummy>(int, int[]) 
{ 
} 
+2

Параметры шаблона по умолчанию не разрешены в C++ 03, только в C++ 0x/11. – Xeo

+1

Извините, я ошибся: вы не можете частично специализировать функцию. – vitke

+0

@Xeo: Я предполагаю, что вы не допустили функции в C++ 03? «Шаблон-аргумент по умолчанию - это шаблон-аргумент (14.3), указанный после' = 'в параметре шаблона. Аргумент шаблона по умолчанию может быть указан для любого типа шаблона-параметра (тип, не-тип, шаблон) Аргумент шаблона по умолчанию может быть указан в объявлении шаблона класса или определении шаблона класса. ** Аргумент-шаблон по умолчанию не должен указываться в объявлении шаблона функции или в шаблоне функции , а также в шаблоне- параметр-список определения элемента шаблона класса. ** " –

9

Просто возьмите специализацию шаблона вне декларации класса. gcc не разрешает встроенную специализацию шаблона.

Как еще один вариант, просто удалите строку template <> , похоже, сработает для меня.

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