2010-12-06 4 views
5

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

Некоторые частичные специализации перекрываются:

template< typename T > struct C { }; 
template< typename T1, typename T2 > struct TRAIT { }; 

template< typename T > struct TRAIT< T, T > { }; 
template< typename T1, typename T2 > struct TRAIT< C<T1>, C<T2> > { }; 

int main() { 
    // ERROR! could be both TRAIT<T,T> [with T = C<int>] 
    //     and TRAIT<T1,T2> [with T1 = T2 = int] 
    TRAIT< C<int>, C<int> > foo; 
    return 0; 
}; 

Как я должен получить тот же результат с рабочим кодом?

Я пошел с ума enable_if и is_same, я даже не уверен, что больше это правильный путь ...

+2

Что вы ** действительно ** пытаетесь сделать? – 2010-12-06 21:22:17

+2

Вам следует избегать перекрытия. Это ответ. Вопрос заключается в вопросе Карла: что вы действительно пытаетесь сделать? – 2010-12-06 21:25:50

+0

Прошу прощения, но вы используете C++ неправильно. Пересмотрите свое решение и \ или опубликуйте фактическую проблему, чтобы получить реальный ответ. – Squirrelsama 2010-12-06 21:31:36

ответ

6

Лучше всего для этого, если вы не можете избежать перекрывающихся специализации, чтобы прояснить все перекрывается. Вам нужно написать еще одну специализацию

template< typename T> struct TRAIT< C<T>, C<T> > { }; 

... но, как и все остальные сказали в комментариях, то лучше, чтобы избежать дублирования, если вообще возможно. Как говорили другие, проблема может быть не совпадающей специализацией, возможно, это не лучший подход к решению вашей проблемы.

0

Try:

template< typename T > struct C { }; 
template< typename T1, typename T2 = T1> struct TRAIT { }; 
           // ^^^^^^^^^ 
           // Default Type is T1 

int main() 
{ 
     TRAIT<C<int> >   foo1; 
     TRAIT<C<int>, C<int> > foo2; 

     foo1 = foo2; 
     return 0; 
}; 
0

Хитрость заключается в том, чтобы создать тип помощника, который говорит вам, если что-то есть C<Foo> или нет:

template <typename T> struct C {}; 

template <typename T> struct is_C { 
    static bool const value = false; 
}; 
template <typename T> struct is_C<C<T>> { 
    static bool const value = true; 
}; 

Вы были на правильном пути с enable_if но is_same кажется в качестве тупика:

#include <type_traits> 

template <typename T1, typename T2, typename Enabled = void> struct Trait { 
    static char const test = 'D'; // default 
}; 

template <typename T> struct Trait< 
    T, 
    T, 
    typename std::enable_if<!is_C<T>::value >::type 
> { 
    static char const test = 'N'; // non-C 
}; 

template <typename T1, typename T2> struct Trait< 
    T1, 
    T2, 
    typename std::enable_if< is_C<T1>::value && is_C<T2>::value >::type 
> { 
    static char const test = 'C'; // some C 
}; 

который вы можете проверить легко прямо сейчас:

#include <iostream> 

int main() { 
    Trait< C<int>, C<float> > foo1a; 
    Trait< C<int>, C<int> > foo1b; 
    Trait< int, int > foo2; 
    Trait< int, float > foo3; 
    std::cout << "Trait<C<int>,C<float>> : " << foo1a.test << std::endl; // prints 'C' 
    std::cout << "Trait<C<int>,C<int>> : " << foo1b.test << std::endl; // prints 'C' 
    std::cout << "Trait<int,int> : " << foo2.test << std::endl; // prints 'N' 
    std::cout << "Trait<int,float> : " << foo3.test << std::endl; // prints 'D' 
    return 0; 
} 

Вы можете легко изменить, что если вы хотите, чтобы ваша специализация работать только с одним из параметров, чтобы быть C или что угодно.

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