Ошибка компилятора C2766: «явная специализация;« специализация »уже определена» при использовании boost :: disable_if - PullRequest
2 голосов
/ 19 января 2012

Я пытаюсь создать шаблон класса Fod

template<typename S0 = aux::EmptyType, typename S1 = aux::EmptyType, typename S2 = aux::EmptyType, typename S3 = aux::EmptyType, typename S4 = aux::EmptyType, typename S5 = aux::EmptyType, typename S6 = aux::EmptyType, typename S7 = aux::EmptyType, typename S8 = aux::EmptyType, typename S9 = aux::EmptyType>
class Fod { ... };

, который будет содержать внутренний класс At с static const int value, указывающим индекс аргумента шаблона (0 для S0, 1 для S1 и т. Д.). Вкратце, оно должно удовлетворять условию:

struct Type0 {}; struct Type1 {};
BOOST_STATIC_ASSERT( (Fod<Type0>::At<Type0>::value == 0) );
BOOST_STATIC_ASSERT( (Fod<Type0, Type1>::At<Type0>::value == 0) );
BOOST_STATIC_ASSERT( (Fod<Type0, Type1>::At<Type1>::value == 1) );

Я пытался использовать boost::disable_if следующим образом:

template<class T, class Enable = void>
class At; // undefined

template<>
struct At<S0, typename boost::disable_if<boost::is_same<S0, aux::EmptyType> >::type > {
    static const int value = 0;
};

template<>
struct At<S1, typename boost::disable_if<boost::is_same<S1, aux::EmptyType> >::type > {
    static const int value = 1;
};

template<>
struct At<S2, typename boost::disable_if<boost::is_same<S2, aux::EmptyType> >::type > {
    static const int value = 2;
};

template<>
struct At<S3, typename boost::disable_if<boost::is_same<S3, aux::EmptyType> >::type > {
    static const int value = 3;
};

// and so on for S4...S9

но это приводит к ошибке, когда я определяю специализацию для S3, и оба S2, S3 относятся к одному типу aux::EmptyType (или: я определяю специализацию для S2, и оба S1, S2 относятся к одному типу).

4>C:\phd\cpp\src\boost/dst/fod.hpp(144): error C2766: explicit specialization ; 'boost::dst::fod<S0>::At<boost::dst::aux::EmptyType,boost::mpl::s_item<T,Base>>' has already been defined
4>          with
4>          [
4>              S0=Type0
4>          ]
4>          and
4>          [
4>              T=Type0,
4>              Base=boost::mpl::set0<>::item_
4>          ]

Есть идеи, как решить проблему? И если бы я хотел, чтобы метод size_t at<S0>() дал 0, size_t at<S1>() чтобы дать 1 ...?

Пожалуйста, спросите, нужна ли вам дополнительная информация.

Ответы [ 3 ]

1 голос
/ 19 января 2012

Для этого есть более простое решение, если предположить, что boost :: is_same :: value возвращает 0 или 1 (если ваш bool использует разные значения, просто напишите небольшой конвертер времени компиляции): Замените ваш текущий At на

template <typename T>
struct At {
    enum {
        value = 
        boost::is_same<T, S0>::value) + 
        boost::is_same<T, S1>::value * 10 + 
        boost::is_same<T, S2>::value * 100
    };
};

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

0 голосов
/ 19 января 2012

Я также ответил на мой первый вопрос. На самом деле мне было проще подумать:

// main general template (unused or throws a compilation error)
template<class T, class Enable = void >
struct At {};

template<typename T>
struct At<T, typename boost::enable_if< boost::is_same<T, S0> >::type >
{
    static const int value = 0;
};
// and so on for each class template parameter S1,...,S9
0 голосов
/ 19 января 2012

Мне удалось ответить на второй вопрос (о функции шаблона) частично благодаря этому ответу :

#include <boost/utility/enable_if.hpp>

template <typename T>
static int at(typename boost::enable_if_c< boost::is_same<T, S0>::value && !boost::is_same<T, aux::EmptyType>::value, T >::type = T())
{
    return 0;
}
// and so on for each class template parameter S1,...,S9
...