-1

I know this question have been already asked and answered, but even with that, I cannot figure it out

    In file included from /usr/include/c++/9.2.0/x86_64-pc-linux-gnu/bits/c++allocator.h:33,
                     from /usr/include/c++/9.2.0/bits/allocator.h:46,
                     from /usr/include/c++/9.2.0/list:61,
                     from src/composants/List/List.hpp:14,
                     from src/composants/List/List.cpp:8:
    /usr/include/c++/9.2.0/ext/new_allocator.h: In instantiation of ‘void __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = Entity_c; _Args = {const Entity_c&}; _Tp = std::_List_node<Entity_c>]’:
    /usr/include/c++/9.2.0/bits/alloc_traits.h:482:2:   required from ‘static void std::allocator_traits<std::allocator<_Tp1> >::construct(std::allocator_traits<std::allocator<_Tp1> >::allocator_type&, _Up*, _Args&& ...) [with _Up = Entity_c; _Args = {const Entity_c&}; _Tp = std::_List_node<Entity_c>; std::allocator_traits<std::allocator<_Tp1> >::allocator_type = std::allocator<std::_List_node<Entity_c> >]’
    /usr/include/c++/9.2.0/bits/stl_list.h:633:33:   required from ‘std::__cxx11::list<_Tp, _Alloc>::_Node* std::__cxx11::list<_Tp, _Alloc>::_M_create_node(_Args&& ...) [with _Args = {const Entity_c&}; _Tp = Entity_c; _Alloc = std::allocator<Entity_c>; std::__cxx11::list<_Tp, _Alloc>::_Node = std::_List_node<Entity_c>]’
    /usr/include/c++/9.2.0/bits/stl_list.h:1907:10:   required from ‘void std::__cxx11::list<_Tp, _Alloc>::_M_insert(std::__cxx11::list<_Tp, _Alloc>::iterator, _Args&& ...) [with _Args = {const Entity_c&}; _Tp = Entity_c; _Alloc = std::allocator<Entity_c>; std::__cxx11::list<_Tp, _Alloc>::iterator = std::_List_iterator<Entity_c>]’
    /usr/include/c++/9.2.0/bits/stl_list.h:1208:9:   required from ‘void std::__cxx11::list<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = Entity_c; _Alloc = std::allocator<Entity_c>; std::__cxx11::list<_Tp, _Alloc>::value_type = Entity_c]’
    src/composants/List/List.cpp:57:29:   required from here
    /usr/include/c++/9.2.0/ext/new_allocator.h:145:20: error: use of deleted function ‘Entity_c::Entity_c(const Entity_c&)’
      145 |  noexcept(noexcept(::new((void *)__p)
          |                    ^~~~~~~~~~~~~~~~~~
      146 |        _Up(std::forward<_Args>(__args)...)))
          |        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    In file included from src/composants/List/List.cpp:9:
    src/composants/Entity/Entity.hpp:16:7: note: ‘Entity_c::Entity_c(const Entity_c&)’ is implicitly deleted because the default definition would be ill-formed:
       16 | class Entity_c {
          |       ^~~~~~~~
    src/composants/Entity/Entity.hpp:16:7: error: use of deleted function ‘sf::Mutex::Mutex(const sf::Mutex&)’
    In file included from src/composants/List/List.hpp:12,
                     from src/composants/List/List.cpp:8:
    /usr/include/SFML/System/Mutex.hpp:47:23: note: ‘sf::Mutex::Mutex(const sf::Mutex&)’ is implicitly deleted because the default definition would be ill-formed:
       47 | class SFML_SYSTEM_API Mutex : NonCopyable
          |                       ^~~~~
    /usr/include/SFML/System/Mutex.hpp:47:23: error: ‘sf::NonCopyable::NonCopyable(const sf::NonCopyable&)’ is private within this context
    In file included from /usr/include/SFML/System/Thread.hpp:32,
                     from src/composants/List/List.hpp:11,
                     from src/composants/List/List.cpp:8:
    /usr/include/SFML/System/NonCopyable.hpp:77:5: note: declared private here
       77 |     NonCopyable(const NonCopyable&);
          |     ^~~~~~~~~~~
    In file included from src/composants/List/List.cpp:9:
    src/composants/Entity/Entity.hpp:16:7: error: use of deleted function ‘sf::Mutex::Mutex(const sf::Mutex&)’
       16 | class Entity_c {

I do not understand thoses errors, but I've still figured out which part of my code is throwing it :

 54 void List_c::operator++(int)
 55 {
 56     Entity_c *entity = new Entity_c;                                                   
 57     m_list.push_back(*entity);
 58 }

I have to say that I don't really understand why this is throwing something like (as I understood) I'm trying to call Entity_c::Entity_c(const Entity_c&).

Entity_c is defined as follow :

 16 class Entity_c {                
 17 public:                         
 18     Entity_c();                 
 19     ~Entity_c();
 ...
 81 };

Well, it is possible that I just didn't understand that error at all, so please, feel free to show me my mistakes.

DiantArts
  • 104
  • 7
  • If I understand correctly the code that you didn't post, `m_list` is a list of Entity_c, which are held by value. The `push_back` invocation *copies* values into the list, not moves. Also, looks like copy constructor cannot be generated for Entity_c, probably because it has some non-copyable members (without copy constructor). – smitsyn Dec 11 '19 at 14:39
  • `Entity_c` is not defined like that at all. `...` is not valid C++. – molbdnilo Dec 11 '19 at 14:39
  • The `...` part within `Entity_c` is where the problem lies. One of the data members must be non-copyable, probably `sf::Mutex`. And your `operator++` definition leaks memory. Avoid using `new` if you're new to C++. – Praetorian Dec 11 '19 at 14:40
  • @smitsyn to be honnest, it is just too long to post. Everything else (I think) do not help the comprehension. Variables are already explicitly named – DiantArts Dec 11 '19 at 14:41
  • If `Entity_c` absolutely must be non-copyable, you may hold them in list by `std::unique_ptr`. Otherwise, consider making them copyable, and create them without using operator `new`. – smitsyn Dec 11 '19 at 14:42
  • @Praetorian okay I still can post the rest of the class if that helps. But why should I avoid using new ? – DiantArts Dec 11 '19 at 14:43
  • @DiantArts because it leaks memory - operator `new` allocates `Entity_c` objects on the free store (heap), but they are not deleted anywhere. – smitsyn Dec 11 '19 at 14:44
  • so, there is no difference with malloc ? I know that I'll have to call delete else where. I don't want to call new, but If i do not alloc them, those entities will be destroyed at the end of the function – DiantArts Dec 11 '19 at 14:45
  • 1
    @DiantArts maybe take a step back and start by reading a [C++ book](https://stackoverflow.com/q/388242/241631) for beginners. You don't need to `new` within the `operator++` definition you've shown. A typical post-increment operator signature would be `List_c List_c::operator++(int)` and implementing an increment operator for `List_c`, assuming it's a linked-list like class, makes little sense. – Praetorian Dec 11 '19 at 14:49

1 Answers1

0

The main clues are class SFML_SYSTEM_API Mutex : NonCopyable and "use of deleted function ‘sf::Mutex::Mutex(const sf::Mutex&)" - a sf::Mutex can't be copied, and push_back does exactly that.

Since sf::Mutex can't be copied, neither can (by default) things that have one as a member.

You can make Entity_c copyable by adding a copy constructor that doesn't copy the mutex from the original but creates a new one.
(Or avoid copying - see below.)

You should also not create the object with new - you're leaking memory.

Either do this:

Entity_c entity;                                                   
m_list.push_back(entity);

or this:

m_list.push_back(Entity_c{});

or this, which does not require copying at all:

m_list.emplace_back();

(As a side note, that use of ++ is quite surprising. I doubt that you do this so often that you need very terse syntax for it - I would go with List_c::add_entity() or something like that.)

molbdnilo
  • 64,751
  • 3
  • 43
  • 82
  • +Thanks a lot. I've to say first that I know this ++ isn't common. I'm just overloading this operator for the practicaly side. it is just better to do `list++` than `list.add_entity()`. That said, i don't really understand why my object should be copied, since I wanna create a new one from the base constructor. – DiantArts Dec 11 '19 at 14:59
  • I think C++ is really differente from C, because your first exemple wouldn't work at all since the entity created would be destroyed at the end of the function. That the only reason why I've tried to `new` it – DiantArts Dec 11 '19 at 15:00
  • @DiantArts No, they work in the same (safe) way in both languages; the object is copied in both C and C++. When the original is destroyed, the copy still exists. The only way to avoid copying is to use `emplace_back` to create the object in-place. – molbdnilo Dec 11 '19 at 15:04
  • Beware the use of `emplace_back()` still needs the `entity` to be *MoveInsertable and EmplaceConstructible* (see here: https://en.cppreference.com/w/cpp/container/vector/emplace_back). It may work for this case but not in general. – Welgriv Feb 27 '23 at 08:54