Сопоставьте массив фиксированного размера с классом CRTP

#c #templates

#c #шаблоны

Вопрос:

снова его шаблоны 😉 Учитывая следующие функции-члены шаблона и класс CRTP:

 template<typename T>
struct base
{
   ...
};

struct derived : public base<derived>
{
   ...
};

struct some_class
{
    template<typename T>
    void match(base<T>* array, size_t count)
    {
        ...
    };

    template<typename T, size_t count>
    void match(base<T> (amp;array)[count])
    {
        ...
    };
};
 

Почему компилятор не находит соответствия для второй функции:

 derived array[10];
some_class foo;

foo.match(array, 10); // works fine
foo.match(array);     // Error: no matching function for call to some_class::match(derived array[10])
 

Я бы ожидал, что вторая шаблонная функция может вычесть размер массива fixde во время компиляции, но, по-видимому, эта функция не учитывается. Почему?

Спасибо

Редактировать: как ни странно, следующая версия компилируется нормально:

     template<typename T, size_t count>
    void match(T (amp;array)[count])
    {
        ...
    };
 

Поэтому я подозреваю, что в какой-то момент оригинальная версия будет исключена по какой-то причине, которую я просто не вижу.

Ответ №1:

Массив производных не может быть преобразован в массив базовых. Если вы когда-либо делали что-либо с массивом, кроме доступа к первому элементу в первом конструкторе, это было бы неопределенное поведение.

Правильное использование ссылки защищает вас от этой ситуации, поскольку код не компилируется. Однако он будет компилироваться путем разложения массива до одного указателя, который может распадаться до указателя на Base, что делает Base<T>* перегрузку жизнеспособной, но все равно плохой.