compiler error: no appropriate default constructor available
От: Bender Bending Rodriguez Россия  
Дата: 02.04.10 13:04
Оценка:
Всем привет!

минимальный код вызывающий ошибку:


#include <vector>
#include <utility>

class A
{
public:
    A(const int i):m(i){}

private:
    int m;
};

int main()
{
    typedef std::pair< A, std::vector< int > > pair_t;
    typedef std::vector< pair_t > vector_t;

    vector_t vector;

    pair_t el(A(5), std::vector< int >(5, 5));
    vector.push_back(el);

    return 0;
}


MS VisualStudio 2008 выдаёт следующее сообщение:

error C2512: 'A::A' : no appropriate default constructor available


MS VisualStudio 2005 компилирует без проблем. Как и Comeau on-line, codepad.org

Интересное наблюдение: если изменить pair_t с

    typedef std::pair< A, std::vector< int > > pair_t;

на
    typedef std::pair< A, A > pair_t;

то такая конструкция уже не требует default constructor A()

С "наскоку" видна разница в реализации vector::_Insert_n()
ошибка же сама "возникает" в <memory>

template<class _InIt, class _FwdIt, class _Alloc>
inline    _FwdIt _Uninit_move(
    {    // use swap to instead of the copy constructor
        ...

    // empty value used in the construction
    typename _Alloc::value_type _Val;
        ...
        }


но с какого перепуга мы сюда вообще попадаем, мне пока неочевидно

Буду благодарен за идеи и рецепты!
Re: compiler error: no appropriate default constructor avail
От: rus blood Россия  
Дата: 02.04.10 14:02
Оценка: 2 (1)
Здравствуйте, Bender Bending Rodriguez, Вы писали:

BBR>но с какого перепуга мы сюда вообще попадаем, мне пока неочевидно


Это реализация move-стратегии при расширении буфера вектора.
Вектор пытается не скопировать, а перетащить данные из старого буфера в новый.
Для этого буфер предварительно заполняется пустыми объектами, после чего выполняется swap данных.

У меня нет 2008-й, и ты не привел полный список параметров, но по коду 2005-й,
template<class _InIt, class _FwdIt, class _Alloc>
inline    _FwdIt _Uninit_move(

соответствует версии _Uninit_move для типов с поддержкой _Swap_move_tag.
Категория move определяется выше по стеку вызовов, и задается явным перечислением типов.

По-видимому, в 2008-й std::pair объявлен всегда поддерживающим swap ...
Имею скафандр — готов путешествовать!
Re: compiler error: no appropriate default constructor avail
От: uzhas Ниоткуда  
Дата: 02.04.10 14:15
Оценка:
BBR>но с какого перепуга мы сюда вообще попадаем, мне пока неочевидно

не нашел в драфте нового стандарта требование DefaultConstructable для типа объектов в std::vector-е.
похоже на глюк студии.
Re[2]: compiler error: no appropriate default constructor av
От: Bender Bending Rodriguez Россия  
Дата: 02.04.10 15:20
Оценка:
Здравствуйте, rus blood, Вы писали:

RB>У меня нет 2008-й, и ты не привел полный список параметров, но по коду 2005-й,

RB>
RB>template<class _InIt, class _FwdIt, class _Alloc>
RB>inline    _FwdIt _Uninit_move(
RB>

RB>соответствует версии _Uninit_move для типов с поддержкой _Swap_move_tag.
RB>Категория move определяется выше по стеку вызовов, и задается явным перечислением типов.

да, действительно, так и есть есть
template<class _InIt, class _FwdIt, class _Alloc>
inline
    _FwdIt _Uninit_move(_InIt _First, _InIt _Last, _FwdIt _Dest,
        _Alloc& _Al, _Swap_move_tag, _Range_checked_iterator_tag)


её реализация требует наличия конструктора по умолчанию для элементов последовательности.

а у _Swap_move_tag ноги растут отсюда:

<xutulity>
template<class _Ty>
    struct _Is_swap_move
    {    // assumes _Ty is not _Swap_move_tag
    static const bool _Value = false;
    };

template<>
    struct _Is_swap_move<_Swap_move_tag>
    {    // reports true for _Swap_move_tag
    static const bool _Value = true;
    };

template<class _Ty1,
    class _Ty2>
    class _Move_operation_category<pair<_Ty1, _Ty2> >
    {    // reports true if either member of pair is _Swap_move_tag
public:
    typedef typename _If<
        _Is_swap_move<typename _Move_operation_category<
            _Ty1>::_Move_cat>::_Value ||                /// false для класс A
        _Is_swap_move<typename _Move_operation_category<
            _Ty2>::_Move_cat>::_Value,                  /// true для vector< int > (смотри на _Move_operation_category для вектора)
        _Swap_move_tag,
        _Undefined_move_tag>::_Result _Move_cat;            /// получаем _Swap_move_tag, что выглядит несколько странно.
    };

<vector>

    // vector implements a performant swap
template <class _Ty, class _Ax>
    class _Move_operation_category<vector<_Ty, _Ax> >
    {
    public:
        typedef _Swap_move_tag _Move_cat;
    };


Вот такие пироги.
Похоже, что пирожок был испечён SP1 для VS2008
Re[2]: compiler error: no appropriate default constructor av
От: Bender Bending Rodriguez Россия  
Дата: 02.04.10 15:29
Оценка:
Здравствуйте, uzhas, Вы писали:

U>не нашел в драфте нового стандарта требование DefaultConstructable для типа объектов в std::vector-е.

U>похоже на глюк студии.

да, такого требования и нет.
это ошибка введённая Visual C++ 2008 Feature Pack(часть SP1)
Re[3]: compiler error: no appropriate default constructor av
От: rus blood Россия  
Дата: 02.04.10 15:32
Оценка:
Здравствуйте, Bender Bending Rodriguez, Вы писали:

BBR>
BBR>template<class _Ty1,
BBR>    class _Ty2>
BBR>    class _Move_operation_category<pair<_Ty1, _Ty2> >
BBR>    {    // reports true if either member of pair is _Swap_move_tag
BBR>public:
BBR>    typedef typename _If<
BBR>        _Is_swap_move<typename _Move_operation_category<
            _Ty1>>::_Move_cat>::_Value ||                /// false для класс A
BBR>        _Is_swap_move<typename _Move_operation_category<
            _Ty2>>::_Move_cat>::_Value,                  /// true для vector< int > (смотри на _Move_operation_category для вектора)
BBR>        _Swap_move_tag,
BBR>        _Undefined_move_tag>::_Result _Move_cat;            /// получаем _Swap_move_tag, что выглядит несколько странно.
BBR>    };
BBR>


BBR>Вот такие пироги.

BBR>Похоже, что пирожок был испечён SP1 для VS2008

А ты хочешь, чтобы твой pair_t::second копировался по значению???
А если там будет вектор на миллион интов?
Да в твоем внешнем векторе будет миллион пар...

Ну, переопредели тогда _Move_operation_category для своего pair_t и будет тебе "счастье"...

Может, проще все таки сделать ctor по-умолчанию?
Имею скафандр — готов путешествовать!
Re[4]: compiler error: no appropriate default constructor av
От: Bender Bending Rodriguez Россия  
Дата: 02.04.10 15:55
Оценка:
Здравствуйте, rus blood, Вы писали:

RB>А ты хочешь, чтобы твой pair_t::second копировался по значению???

RB>А если там будет вектор на миллион интов?
RB>Да в твоем внешнем векторе будет миллион пар...

Дело не в миллионах.
Дело в том, что сам vector да и vector::push_back не предъявляют к элементам
такого требования как наличиее конструктора по умолчанию.
сурово требуется только:

23.1.3
The type of objects stored in these components must meet the requirements of CopyConstructible
types (20.1.3), and the additional requirements of Assignable types.


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

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

RB>Ну, переопредели тогда _Move_operation_category для своего pair_t и будет тебе "счастье"...

RB>Может, проще все таки сделать ctor по-умолчанию?

Да, конструктор по умолчанию — это самое быстрое и простое решение в моём случае.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.