станд :: список не может быть определено - PullRequest
0 голосов
/ 16 февраля 2020

Я пытаюсь определить постоянный список постоянных объектов, и я не могу этого сделать. Вот мой пример, который прекрасно компилируется:

#include <string>
#include <list>

class Person { public:
    std::string name;
    Person(const std::string &in_name){name=in_name;}
};

class MyClass { public:
    const std::list</* const */Person> l;
    MyClass(const std::list</* const */Person> &in_l):l(in_l){}
};

int main(int argc, char **argv) {
    Person dave("dave");
    MyClass c(std::list<const Person>(dave));
    return 0;
}

Когда я удаляю комментарии из const в этих 2 местах, я получаю следующие ошибки:

In file included from /usr/include/x86_64-linux-gnu/c++/7/bits/c++allocator.h:33:0,
                 from /usr/include/c++/7/bits/allocator.h:46,
                 from /usr/include/c++/7/string:41,
                 from main66.cpp:1:
/usr/include/c++/7/ext/new_allocator.h: In instantiation of ‘class __gnu_cxx::new_allocator<const Person>’:
/usr/include/c++/7/bits/allocator.h:108:11:   required from ‘class std::allocator<const Person>’
main66.cpp:11:53:   required from here
/usr/include/c++/7/ext/new_allocator.h:93:7: error: ‘const _Tp* __gnu_cxx::new_allocator<_Tp>::address(__gnu_cxx::new_allocator<_Tp>::const_reference) const [with _Tp = const Person; __gnu_cxx::new_allocator<_Tp>::const_pointer = const Person*; __gnu_cxx::new_allocator<_Tp>::const_reference = const Person&]’ cannot be overloaded
       address(const_reference __x) const _GLIBCXX_NOEXCEPT
       ^~~~~~~
/usr/include/c++/7/ext/new_allocator.h:89:7: error: with ‘_Tp* __gnu_cxx::new_allocator<_Tp>::address(__gnu_cxx::new_allocator<_Tp>::reference) const [with _Tp = const Person; __gnu_cxx::new_allocator<_Tp>::pointer = const Person*; __gnu_cxx::new_allocator<_Tp>::reference = const Person&]’
       address(reference __x) const _GLIBCXX_NOEXCEPT
       ^~~~~~~

Is Есть ли способ определить std :: список const объектов ?

Ответы [ 3 ]

6 голосов
/ 16 февраля 2020

Контейнеры, поддерживающие распределитель , такие как std::list, не могут принимать const типы значений, потому что Распределитель требования определяют поведение только для cv-неквалифицированные типы. Это означает, что контейнеру не гарантируется возможность создания объектов элементов через интерфейс распределителя, если тип значения квалифицирован как const или volatile.

Это не проблема, поскольку контейнер Быть const достаточно, чтобы гарантировать, что элементы не изменены. Если вы обращаетесь к элементу контейнера через ссылку const на контейнер, вы всегда получите только ссылку const на элемент.

Итак, просто используйте const std::list<Person> вместо const std::list<const Person>.

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

См. также Разрешает ли C ++ 11 вектор ? для деталей.

2 голосов
/ 16 февраля 2020

Сообщение об ошибке кажется достаточно ясным https://gcc.godbolt.org/z/MG3Kxv:

ошибка: stati c утверждение не удалось: std::list должно иметь неконстантное, энергонезависимое value_type

2 голосов
/ 16 февраля 2020

std :: list должен иметь неконстантный, энергонезависимый тип_значения.

...