Передача массива typedef шаблона в конструктор - PullRequest
0 голосов
/ 23 июля 2011

У меня есть шаблонный класс в заголовке, который не компилируется, но когда я пытаюсь создать минимальный пример, он компилируется нормально. Я пытаюсь сделать класс, который может быть построен из массива, автоматически определяя длину. Ошибка в том, что «ссылка на массив нулевого размера недопустима», что не имеет смысла, поскольку она должна автоматически определять длину с помощью шаблона.
Код по теме:

template<class _Elem, bool _Null=true, bool _Trunc=false, class _Traits = std::char_traits<char>>
class basic_estring {
public:
    typedef typename _Traits::pos_type size_type;
    typedef typename _Elem value_type;
    typedef value_type* pointer;
    typedef const value_type* const_pointer;
    typedef value_type &reference;
    typedef const value_type &const_reference;
    static const size_type npos;

    basic_estring(const_pointer ptr, size_type capacity=npos, size_type used=npos);
    template<int capacity> basic_estring(value_type (&data)[capacity], size_type used=npos);
    // several hundred lines of other declarations
};
template<class _Elem, bool _Null, bool _Trunc, class _Traits>
basic_estring<_Elem,_Null,_Trunc,_Traits>::basic_estring(
    typename basic_estring<_Elem,_Null,_Trunc,_Traits>::const_pointer ptr, 
    typename basic_estring<_Elem,_Null,_Trunc,_Traits>::size_type capacity, 
    typename basic_estring<_Elem,_Null,_Trunc,_Traits>::size_type used)
{} //This constructor has no problems (and all the others too)

template<class _Elem, bool _Null, bool _Trunc, class _Traits> template<int capacity> 
basic_estring<_Elem,_Null,_Trunc,_Traits>::basic_estring(
    typename basic_estring<_Elem,_Null,_Trunc,_Traits>::value_type (&data)[capacity], //LINE 218
    typename basic_estring<_Elem,_Null,_Trunc,_Traits>::size_type used)
{} //LINE 228
//several hundred lines of definitions

И ошибка от MSVC C ++ 2010:

1>/*snip*/\estring.h(218): error C2265: 'abstract declarator' : reference to a zero-sized array is illegal
1>/*snip*/\estring.h(228): error C2244: 'basic_estring<_Elem,_Null,_Trunc,_Traits>::{ctor}' : unable to match function definition to an existing declaration
1>  definition
1>  'basic_estring<_Elem,_Null,_Trunc,_Traits>::basic_estring(basic_estring<_Elem,_Null,_Trunc,_Traits>::basic_estring<_Elem,_Null,_Trunc,_Traits>::value_type (&)[1],basic_estring<_Elem,_Null,_Trunc,_Traits>::basic_estring<_Elem,_Null,_Trunc,_Traits>::size_type)'
1>  existing declarations
1>  'basic_estring<_Elem,_Null,_Trunc,_Traits>::basic_estring(const basic_estring<_Elem,_Null,_Trunc,_Traits> &&)'
1>  'basic_estring<_Elem,_Null,_Trunc,_Traits>::basic_estring(const basic_estring<_Elem,_Null,_Trunc,_Traits> &)'
1>  'basic_estring<_Elem,_Null,_Trunc,_Traits>::basic_estring(const std::basic_string<_Elem,_Traits,Alloc> &)'
1>  'basic_estring<_Elem,_Null,_Trunc,_Traits>::basic_estring(_Elem (&)[capacity],_Traits::pos_type)'
1>  'basic_estring<_Elem,_Null,_Trunc,_Traits>::basic_estring(const _Elem *,_Traits::pos_type,_Traits::pos_type)'

Кто-нибудь знает, что я делаю не так? Я обычно довольно хорошо решаю свои собственные проблемы, но это поставило меня в тупик. Я переписал его с других конструкторов, и это ничего не решило.
[Редактировать] Ошибка все еще там, когда непрототипный код в этом проекте

int main() {
    return 0;
}

(включая определения функций) Насколько я могу судить, это не проблема создания экземпляров. Когда я комментировал этот код, я также продолжал комментировать код внутри класса и обнаружил, что если я закомментировал прототип функции-члена capacity, ошибка исчезнет. Мой класс не наследуется ни от каких других классов.

void resize( size_type Count );
void resize( size_type Count, value_type Ch );
size_type capacity( ) const;  //if this is commented, the error goes away.
void reserve( size_type Count );

Теперь я в полном недоумении. [/ Edit]

Ответы [ 2 ]

1 голос
/ 28 июля 2011

Я наконец понял это. Сбой конструктора с типом шаблона capacity, когда у класса также была функция-член capacity. Упс. Проблема исчезнет, ​​когда я переименую с типом шаблона в Cap

1 голос
/ 23 июля 2011

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

Например, этот код скомпилируется просто отлично:

#include <iostream>

template<typename T>
class A
{
    T* array;

    public:
        template<int capacity>
        A(T (&data)[capacity]) { std::cout << capacity << std::endl; }
};

int main()
{
        int array[5];
        A<int> b(array);

        return 0;
}

С другой стороны, изменение объявления array на

int main()
{
    int array[] = {};
    A<int> b(array);

    return 0;
}

Больше не компилируется.Он не может вывести значение шаблона для capacity из входных параметров.На самом деле, gcc не может правильно идентифицировать тип аргумента, так как ошибка выглядит как

prog.cpp: In function ‘int main()’:
prog.cpp:22: error: no matching function for call to ‘A<int>::A(int [0])’
prog.cpp:5: note: candidates are: A<int>::A(const A<int>&)

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

Таким образом, само объявление / определение шаблона конструктора само подойдет, но если высоздаем его экземпляр с массивом нулевой длины, тогда тип аргумента неверен, а шаблон не может быть должным образом создан.Первое, на что я бы обратил внимание на вашу ошибку, это то, где создается ваш basic_estring, а не задается вопросом, что не так с самим конструктором.

...