-1

UPD: So the gist of the solution: If copy constructor exists it prevents move constructor from being called by std::move. Problem solved.
I've tried to write a "thread safe stack" accordingly to lecturer's requirements:

  1. It should store type itself.
  2. For primitive types it should receive/return by copy (as usual in c)
  3. For class-type it shouldn't call redundant copy-constructor on recieve/return. Use shared_ptr to achieve this.

And I can't make number 3 work.

To be more specific: I don't know how to pass shared_ptr to/from such-designed class. And moreover I'm almost sure I've written the class itself syntactically wrong.

#ifndef SAFE_QUEUE
#define SAFE_QUEUE

#include <condition_variable>
#include <thread>
#include <stdlib.h>
#include <queue>
#include <mutex>
#include <chrono>

template<typename T>
class SafeQueue {

public:
    SafeQueue() {
        printf("CONSTRUCTOR\n");
    }

    ~SafeQueue() {
        printf("DESTRUCTOR\n");
    }

    void push(T data) {
        std::unique_lock<std::mutex> lock(_m);
        _queue.push(data);
        printf("Pushed %d\n", data);
        _cv.notify_one();
    }

    void push(std::shared_ptr<T> data) {
        std::unique_lock<std::mutex> lock(_m);
        _queue.push(*data);
        _cv.notify_one();
    }

    bool pop_top(T &outEl) {
        std::unique_lock<std::mutex> lock(_m);
        while (1) {
            bool a;
            if (a = this->_cv.wait_for(lock, std::chrono::milliseconds(1000),
                                       [this]() -> bool { return !(this->_queue.empty()); })) {
                printf(" \n\n//Wait for returned %d \n", a);
                if (!(_queue.empty())) {
                    outEl = _queue.front();
                    _queue.pop();
                    return true;
                } else {
                    continue;
                }
            } else {
                printf(" \n\n//Wait for returned %d \n", a);
                printf("Queue is empty\n");
                return false;
            }
        }
    }

    std::shared_ptr<T> pop_top() {
        std::unique_lock<std::mutex> lock(_m);
        while (1) {
            bool a;
            if (a = this->_cv.wait_for(lock, std::chrono::milliseconds(1000),
                                       [this]() -> bool { return !(this->_queue.empty()); })) {
                printf(" \n\n//Wait for returned %d \n", a);
                if (!(_queue.empty())) {
                    std::shared_ptr<T> cur = std::make_shared<T>(_queue.front());
                    _queue.pop();

                    return cur;
                } else {
                    continue;
                }
            } else {
                printf(" \n\n//Wait for returned %d \n", a);
                printf("Queue is empty\n");
                return nullptr;
            }
        }
    }

private:
    std::queue<T> _queue;
    std::condition_variable _cv;
    std::mutex _m;
};


#endif

main:

#include <iostream>
#include "safeQueue.h"
#include <vector>


void forEven(SafeQueue<int> *sq, int numThread){
    // for(int i=0;i<3;i++)
    //  sq->push(i+numThread);
    // sq->push(1);
    // for(int i=0;i<2;i++)
    //sq->push(numThread);
    int z;
    if(sq->pop_top(z))
    printf("even popped:%d\n", z);
    sq->push(numThread);
    printf("even pushed:%d\n", numThread);
}

class myclass{
public:
    int val;
    myclass(myclass &obj){
        printf("copy constructor");
    }
    myclass(int val):val(val){
        printf("constructor");
    }
    ~myclass(){
        printf("destructor");
    }
};

void forOdd(SafeQueue<int> *sq, int numThread){
    int z;
    if(sq->pop_top(z))
    printf("odd popped:%d\n", z);
    if(sq->pop_top(z))
    printf("odd popped:%d\n", z);


    for(int i=0;i<2;i++) {
        sq->push(i + numThread);
        printf("odd pushed:%d\n", i + numThread);
    }

    if(sq->pop_top(z))
    printf("odd popped:%d\n", z);
    if(sq->pop_top(z))

printf("odd popped:%d\n", z);
}

void forEven_class(SafeQueue<myclass> *sq, myclass &el){
    // for(int i=0;i<3;i++)
    //  sq->push(i+numThread);
    // sq->push(1);
    // for(int i=0;i<2;i++)
    //sq->push(numThread);
    std::shared_ptr<myclass> z = std::move(sq->pop_top());
    if(z)
        printf("even popped:%d\n", z->val);
    sq->push(std::make_shared<myclass>(el));
    printf("even pushed:%d\n", el.val);
}

void forOdd_class(SafeQueue<myclass> *sq, myclass &el){
    std::shared_ptr<myclass> z = std::move(sq->pop_top());
    if(z)
    printf("odd popped:%d\n", z->val);
    z = std::move(sq->pop_top());
    if(z)
        printf("odd popped:%d\n", z->val);


    for(int i=0;i<2;i++) {
        sq->push(std::make_shared<myclass>(i + el.val));
        printf("odd pushed:%d\n", i + el.val);
    }

    z = std::move(sq->pop_top());
    if(z)
        printf("odd popped:%d\n", z->val);
    z = std::move(sq->pop_top());
    if(z)
        printf("odd popped:%d\n", z->val);
}

int main(){
    SafeQueue<int> sq;

    SafeQueue<myclass> sq_c;

    std::vector<std::thread> v_t;

    for(int i=0;i<5;i++){
        if( i%2 )
            v_t.push_back(move(std::thread(forOdd,&sq,i+1)));
        else
            v_t.push_back(move(std::thread(forEven,&sq,i+1)));
    }

    for(int i=0;i<5;i++){
        v_t[i].join();
    }

    std::cout << "class test" <<std::endl;
    for(int i=0;i<5;i++){
        if( i%2 )
            v_t.push_back(move(std::thread(forOdd_class,&sq_c,std::move(myclass(i+1)))));
        else
            v_t.push_back(move(std::thread(forEven_class,&sq_c,std::move(myclass(i+1)))));
    }

    for(int i=0;i<5;i++){
        v_t[i].join();
    }

    // std::thread t1(forThreads,&sq,1);
    // std::thread t2(forThreads,&sq,2);
    // std::thread t3(forThreads,&sq,2);
    //
    // t1.join();
    // t2.join();
    // t3.join();


    return 0;
}

I can't make forEven_class() and forOdd_class() work because of enourmous errors:

If I leave uncommented definition only of forEven/Odd_class functions I get:

error: no matching function for call to ‘myclass::myclass(const myclass&)’

So it seems shared ptr attempts to call copy constructor

And if I uncomment everything I get the whole:

In file included from /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/mutex:42:0,
                 from /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/condition_variable:39,
                 from /gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/safeQueue.h:9,
                 from /gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:2:
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/functional: In instantiation of ‘struct std::_Bind_simple<void (*(SafeQueue<myclass>*, myclass))(SafeQueue<myclass>*, myclass&)>’:
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/thread:137:47:   required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (&)(SafeQueue<myclass>*, myclass&); _Args = {SafeQueue<myclass>*, myclass}]’
/gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:116:86:   required from here
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/functional:1665:61: error: no type named ‘type’ in ‘class std::result_of<void (*(SafeQueue<myclass>*, myclass))(SafeQueue<myclass>*, myclass&)>’
       typedef typename result_of<_Callable(_Args...)>::type result_type;
                                                             ^
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/functional:1695:9: error: no type named ‘type’ in ‘class std::result_of<void (*(SafeQueue<myclass>*, myclass))(SafeQueue<myclass>*, myclass&)>’
         _M_invoke(_Index_tuple<_Indices...>)
         ^
In file included from /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/mutex:38:0,
                 from /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/condition_variable:39,
                 from /gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/safeQueue.h:9,
                 from /gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:2:
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/tuple: In instantiation of ‘struct std::_Head_base<2ul, myclass, false>’:
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/tuple:231:12:   recursively required from ‘struct std::_Tuple_impl<1ul, SafeQueue<myclass>*, myclass>’
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/tuple:231:12:   required from ‘struct std::_Tuple_impl<0ul, void (*)(SafeQueue<myclass>*, myclass&), SafeQueue<myclass>*, myclass>’
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/tuple:390:11:   required from ‘class std::tuple<void (*)(SafeQueue<myclass>*, myclass&), SafeQueue<myclass>*, myclass>’
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/functional:1703:39:   required from ‘struct std::_Bind_simple<void (*(SafeQueue<myclass>*, myclass))(SafeQueue<myclass>*, myclass&)>’
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/thread:137:47:   required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (&)(SafeQueue<myclass>*, myclass&); _Args = {SafeQueue<myclass>*, myclass}]’
/gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:116:86:   required from here
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/tuple:137:17: error: ‘constexpr std::_Head_base<_Idx, _Head, false>::_Head_base(const std::_Head_base<_Idx, _Head, false>&) [with long unsigned int _Idx = 2ul; _Head = myclass]’ declared to take const reference, but implicit declaration would take non-const
       constexpr _Head_base(const _Head_base&) = default;
                 ^
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/tuple: In instantiation of ‘constexpr std::_Head_base<_Idx, _Head, false>::_Head_base(_UHead&&) [with _UHead = myclass; long unsigned int _Idx = 2ul; _Head = myclass]’:
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/tuple:273:42:   required from ‘constexpr std::_Tuple_impl<_Idx, _Head, _Tail ...>::_Tuple_impl(std::_Tuple_impl<_Idx, _Head, _Tail ...>&&) [with long unsigned int _Idx = 2ul; _Head = myclass; _Tail = {}]’
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/type_traits:900:43:   required by substitution of ‘template<class _Tp, class _Arg, class> static std::true_type std::__do_is_direct_constructible_impl::__test(int) [with _Tp = std::_Tuple_impl<2ul, myclass>; _Arg = std::_Tuple_impl<2ul, myclass>&&; <template-parameter-1-3> = <missing>]’
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/type_traits:912:43:   required from ‘struct std::__is_direct_constructible_impl<std::_Tuple_impl<2ul, myclass>, std::_Tuple_impl<2ul, myclass>&&>’
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/type_traits:134:12:   required from ‘struct std::__and_<std::is_destructible<std::_Tuple_impl<2ul, myclass> >, std::__is_direct_constructible_impl<std::_Tuple_impl<2ul, myclass>, std::_Tuple_impl<2ul, myclass>&&> >’
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/type_traits:916:12:   required from ‘struct std::__is_direct_constructible_new_safe<std::_Tuple_impl<2ul, myclass>, std::_Tuple_impl<2ul, myclass>&&>’
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/type_traits:994:12:   [ skipping 21 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/type_traits:1175:12:   required from ‘struct std::is_nothrow_move_constructible<std::_Tuple_impl<1ul, SafeQueue<myclass>*, myclass> >’
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/type_traits:134:12:   required from ‘struct std::__and_<std::is_nothrow_move_constructible<void (*)(SafeQueue<myclass>*, myclass&)>, std::is_nothrow_move_constructible<std::_Tuple_impl<1ul, SafeQueue<myclass>*, myclass> > >’
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/tuple:269:7:   required from ‘constexpr std::_Tuple_impl<_Idx, _Head, _Tail ...>::_Tuple_impl(std::_Tuple_impl<_Idx, _Head, _Tail ...>&&) [with long unsigned int _Idx = 0ul; _Head = void (*)(SafeQueue<myclass>*, myclass&); _Tail = {SafeQueue<myclass>*, myclass}]’
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/functional:1727:41:   required from ‘typename std::_Bind_simple_helper<_Func, _BoundArgs>::__type std::__bind_simple(_Callable&&, _Args&& ...) [with _Callable = void (&)(SafeQueue<myclass>*, myclass&); _Args = {SafeQueue<myclass>*, myclass}; typename std::_Bind_simple_helper<_Func, _BoundArgs>::__type = std::_Bind_simple<void (*(SafeQueue<myclass>*, myclass))(SafeQueue<myclass>*, myclass&)>]’
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/thread:137:47:   required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (&)(SafeQueue<myclass>*, myclass&); _Args = {SafeQueue<myclass>*, myclass}]’
/gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:116:86:   required from here
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/tuple:142:42: error: no matching function for call to ‘myclass::myclass(myclass)’
  : _M_head_impl(std::forward<_UHead>(__h)) { }
                                          ^
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/tuple:142:42: note: candidates are:
/gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:32:5: note: myclass::myclass(int)
     myclass(int val):val(val){
     ^
/gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:32:5: note:   no known conversion for argument 1 from ‘myclass’ to ‘int’
/gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:29:5: note: myclass::myclass(myclass&)
     myclass(myclass &obj){
     ^
/gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:29:5: note:   no known conversion for argument 1 from ‘myclass’ to ‘myclass&’
In file included from /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/mutex:38:0,
                 from /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/condition_variable:39,
                 from /gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/safeQueue.h:9,
                 from /gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:2:
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/tuple: In instantiation of ‘constexpr std::_Head_base<_Idx, _Head, false>::_Head_base(const _Head&) [with long unsigned int _Idx = 2ul; _Head = myclass]’:
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/tuple:257:44:   recursively required from ‘constexpr std::_Tuple_impl<_Idx, _Head, _Tail ...>::_Tuple_impl(const _Head&, const _Tail& ...) [with long unsigned int _Idx = 1ul; _Head = SafeQueue<myclass>*; _Tail = {myclass}]’
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/tuple:257:44:   required from ‘constexpr std::_Tuple_impl<_Idx, _Head, _Tail ...>::_Tuple_impl(const _Head&, const _Tail& ...) [with long unsigned int _Idx = 0ul; _Head = void (*)(SafeQueue<myclass>*, myclass&); _Tail = {SafeQueue<myclass>*, myclass}]’
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/tuple:400:33:   required from ‘constexpr std::tuple< <template-parameter-1-1> >::tuple(const _Elements& ...) [with _Elements = {void (*)(SafeQueue<myclass>*, myclass&), SafeQueue<myclass>*, myclass}]’
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/functional:1678:74:   required from ‘std::_Bind_simple<_Callable(_Args ...)>::_Bind_simple(_Callable&&, _Args2&& ...) [with _Args2 = {SafeQueue<myclass>*, myclass}; <template-parameter-2-2> = void; _Callable = void (*)(SafeQueue<myclass>*, myclass&); _Args = {SafeQueue<myclass>*, myclass}]’
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/functional:1727:41:   required from ‘typename std::_Bind_simple_helper<_Func, _BoundArgs>::__type std::__bind_simple(_Callable&&, _Args&& ...) [with _Callable = void (&)(SafeQueue<myclass>*, myclass&); _Args = {SafeQueue<myclass>*, myclass}; typename std::_Bind_simple_helper<_Func, _BoundArgs>::__type = std::_Bind_simple<void (*(SafeQueue<myclass>*, myclass))(SafeQueue<myclass>*, myclass&)>]’
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/thread:137:47:   required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (&)(SafeQueue<myclass>*, myclass&); _Args = {SafeQueue<myclass>*, myclass}]’
/gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:116:86:   required from here
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/tuple:135:25: error: no matching function for call to ‘myclass::myclass(const myclass&)’
       : _M_head_impl(__h) { }
                         ^
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/tuple:135:25: note: candidates are:
/gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:32:5: note: myclass::myclass(int)
     myclass(int val):val(val){
     ^
/gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:32:5: note:   no known conversion for argument 1 from ‘const myclass’ to ‘int’
/gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:29:5: note: myclass::myclass(myclass&)
     myclass(myclass &obj){
     ^
/gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:29:5: note:   no known conversion for argument 1 from ‘const myclass’ to ‘myclass&’
In file included from /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/x86_64-redhat-linux/bits/c++allocator.h:33:0,
                 from /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/bits/allocator.h:46,
                 from /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/string:41,
                 from /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/bits/locale_classes.h:40,
                 from /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/bits/ios_base.h:41,
                 from /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/ios:42,
                 from /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/ostream:38,
                 from /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/iostream:39,
                 from /gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:1:
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/ext/new_allocator.h: In instantiation of ‘void __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = myclass; _Args = {const myclass&}; _Tp = myclass]’:
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/bits/stl_deque.h:1403:6:   required from ‘void std::deque<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = myclass; _Alloc = std::allocator<myclass>; std::deque<_Tp, _Alloc>::value_type = myclass]’
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/bits/stl_queue.h:216:9:   required from ‘void std::queue<_Tp, _Sequence>::push(const value_type&) [with _Tp = myclass; _Sequence = std::deque<myclass, std::allocator<myclass> >; std::queue<_Tp, _Sequence>::value_type = myclass]’
/gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/safeQueue.h:37:9:   required from ‘void SafeQueue<T>::push(std::shared_ptr<_Tp1>) [with T = myclass]’
/gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:69:43:   required from here
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/ext/new_allocator.h:120:4: error: no matching function for call to ‘myclass::myclass(const myclass&)’
  { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
    ^
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/ext/new_allocator.h:120:4: note: candidates are:
/gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:32:5: note: myclass::myclass(int)
     myclass(int val):val(val){
     ^
/gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:32:5: note:   no known conversion for argument 1 from ‘const myclass’ to ‘int’
/gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:29:5: note: myclass::myclass(myclass&)
     myclass(myclass &obj){
     ^
/gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:29:5: note:   no known conversion for argument 1 from ‘const myclass’ to ‘myclass&’

So I don't know how to use shared_ptr at all. (especially passing it to thread) I might have got the lecturer wrong. So what would you recommend to use: unque_ptr or what?

Rules
  • 103
  • 1
  • 12
  • _"Can't make work"_ Is a too vague problem description. Post a [MCVE] that reproduces your problem please. – πάντα ῥεῖ Jun 16 '17 at 10:23
  • "I can't make x work" is not an adequate fault report from a student learning to code. You need to tell us what you expected and what you actually got, as a bare minimum. – Rook Jun 16 '17 at 10:23
  • Please read [MCVE] – Richard Critten Jun 16 '17 at 10:25
  • "Use shared_ptr to achieve this" .. I doubt that this is a great idea. Where do you share ownership if you pop something out of a stack? If that's an requirement given from your advisor you should try to get a better​ advisor.. – Daniel Jour Jun 16 '17 at 10:26
  • FYI, I can't compile your code under VS2017. Are you able to compile it? Under which compiler (and version)? – Rook Jun 16 '17 at 10:28
  • @Rook - that's the problem - I CAN'T write it the way so that it could be compiled( . I've tried for several hours. – Rules Jun 16 '17 at 10:55
  • 1
    And _that_ is why you need to include all the relevant details in your question. – Rook Jun 16 '17 at 11:09
  • What is your last working copy of that code? – Marek Vitek Jun 16 '17 at 13:46
  • Here is where you tell your compiler to call copy constructor `std::shared_ptr z = std::move(sq->pop_top());` – Marek Vitek Jun 16 '17 at 13:54
  • You should either provide move constructor, or remove copy constructor and destructor. By defining these you are preventing compiler from creating move constructor for you. – Marek Vitek Jun 16 '17 at 14:03
  • See this SO on [automatic generation of move operations](https://stackoverflow.com/questions/24342941/what-are-the-rules-for-automatic-generation-of-move-operations) – Marek Vitek Jun 16 '17 at 14:09
  • @Marek Vivek. Latest working copy will be if we remove everything concerning shared_ptr. I thought the very meaning of STD::move was to SKIP copy constructor... – Rules Jun 16 '17 at 16:03
  • 1
    Yes, but it uses move constructor. If move constructor is not defined, then it uses copy constructor as fallback. It is good, that you have something that works. You can pull that version and try to apply what you already have in smaller steps and see when it breaks. Then you will know what broke your code. – Marek Vitek Jun 16 '17 at 16:18
  • Remove your unnecessary constructors and change functions forEven_class and forOdd_class and your code will [compile again](https://godbolt.org/g/zb8PCh) – Marek Vitek Jun 16 '17 at 17:35
  • @MarekVitek wow thanks a lot! Why haven't you posted it as an answer rather than as a comment? Turn it into answer And i'll accept it! And BTW I intentionally put ` myclass(myclass &obj){ printf("copy constructor"); }` into my class to test it How then do I test that copy constructor is NOT called? – Rules Jun 16 '17 at 21:09

1 Answers1

1

Remove your unnecessary constructors and destructors and change functions forEven_class and forOdd_class and your code will compile again.
Why removing constructors? Because compiler has rules how to generate default constructors. In your case you wanted move constructor generated, but by defining copy constructor and destructor, you prevented compiler from doing so. Your options are:

  • properly define all constructors including move constructor
  • remove copy constructor and destructor as I suggested since they doesn't do anything execpt debut output
  • instruct compiler to generate default move constructor myclass(myclass &&obj) = default

See this SO on automatic generation of move operations I you want those debug messages, then you have to define those constructors properly. Including task they have to do other than your debug messages.

Regarding changes in functions forEven_class you can´t take the myclass by reference because it is not an lvalue. For more info on this google rvalue reference.

Marek Vitek
  • 1,573
  • 9
  • 20