Ошибка C ++ при различении специализации при передаче константного массива

рассмотреть код

     template <class A>
class B;

template <class A>
class B<const A>{};

template <class A, int N>
class B<A[N]>{};

template <class A>
class B<A*>{};

template <class A>
class B<A&>{};

Следующие экземпляры шаблона работают нормально:

     A<int*&>
A<const int*>
A<int*[3]>

но следующий не работает:

     A<const int[3]>

Есть ли какая-то причина, по которой эта конкретная комбинация недопустима или это, возможно, ошибка в g ++ 4.6.3?

Кстати, мне удалось обойти это с помощью SFINAE и boost :: disable_if<> Так что хотя бы проблема решена.

РЕДАКТИРОВАТЬ

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

EDIT2

Это не имеет ничего общего с указателями, вот полный контекст:

Я прохожу книгу Шаблон метапрограммирования на С ++ и я делаю вопрос 2-3 (глава 2 вопрос 3), который говорит:

Используйте возможности признаков типа для реализации шаблона класса type_descriptor, экземпляры которого, при потоковой передаче, печатают тип своих параметров шаблона:
ПРИМЕЧАНИЕ: мы не можем использовать RTTI с тем же эффектом, поскольку, согласно пункту 7 стандарта [lib.type.info] 18.5.1, typeid (T) .name () не гарантирует возвращение значимого результата.

Мое решение (включая обходной путь для ошибки компиляции) заключается в следующем:

    //QUESTION 2-3
template <class T, class enable = void>
struct type_descriptor
{
std::string operator()() const
{
return "Unknown";
}
};

//specializations for primitive types
#define TYPE_DESC_SPEC(type) template <>    \
struct type_descriptor<type,void>     \
{std::string operator()() const{return #type;}};

TYPE_DESC_SPEC(int)
TYPE_DESC_SPEC(long)
TYPE_DESC_SPEC(void)
TYPE_DESC_SPEC(short)
TYPE_DESC_SPEC(unsigned char)
TYPE_DESC_SPEC(unsigned short)
TYPE_DESC_SPEC(unsigned long)

//specializations for modifiers *, const, &, and [N]

template <class T>
struct type_descriptor<T&,void>
{std::string operator()(){return type_descriptor<T>()() + " &";}};

template <class T>
struct type_descriptor<T*,void>
{std::string operator()(){return type_descriptor<T>()() + " *";}};

//Replace void with what's in the comment for the workaround.
template <class T>
struct type_descriptor<const T, void/*typename boost::disable_if<boost::is_array<T> >::type*/>
{std::string operator()(){return type_descriptor<T>()() + " const";}};

template <class T>
struct type_descriptor<T(*)(),void>
{std::string operator()(){return type_descriptor<T>()() + " (*)()";}};

template <class T, class U>
struct type_descriptor<T(*)(U),void>
{std::string operator()(){return type_descriptor<T>()() + " (*)(" + type_descriptor<U>()() + ")";}};

template <class T, int N>
struct type_descriptor<T[N],void>
{
std::string operator()()
{
std::stringstream s;
s << type_descriptor<T>()() << " [" << N << "]";
return s.str();
}
};

template <class T>
struct type_descriptor<T[],void>
{std::string operator()(){return type_descriptor<T>()() + " []";}};

//Now overload operator<< to allow streaming of this class directly

template <class T>
std::ostream & operator<<(std::ostream & s, type_descriptor<T> t)
{
return s << t();
}
//END QUESTION 2-3

Пример использования:

      std::cout << "\nQuestion 2-3 results\n";
std::cout << type_descriptor<int*>() << std::endl;
std::cout << type_descriptor<int*[3]>() << std::endl;
std::cout << type_descriptor<std::string*>() << std::endl;
std::cout << type_descriptor<const int&>() << std::endl;
std::cout << type_descriptor<const int *const&>() << std::endl;
std::cout << type_descriptor<int[4]>() << std::endl;
std::cout << type_descriptor<int(*)()>() << std::endl;
std::cout << type_descriptor<int*&(*)(const char &)>() << std::endl;
std::cout << type_descriptor<int*&>() << std::endl;
std::cout << type_descriptor<int[]>() << std::endl;
std::cout << type_descriptor<const long[]>() << std::endl;

и соответствующий вывод (когда обходной путь включен, в противном случае он не компилируется на последнем):

int *

int * [3]

Неизвестно *

Int Const 

int const * const 

int [4]

int (*) ()

int *  (*) (Неизвестный конст )

int * 

int []

длинный конст []

Таким образом, C ++ способен различать указатели и массивы для параметров шаблона, способен корректно, рекурсивно разделять составные типы и выводить правильный результат, кроме const A[], Нужна помощь с этим

5

Решение

Тип массива с типом элемента const является одновременно квалифицированным типом const (const применяется двунаправленно) и типом массива.

Таким образом, вы должны исправить специализации.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]