Apple CLang - Classes call to implicitly-deleted copy constructor???

I have been following a book about concurrent C++ code execution, trying to get one of the examples to compile.. but getting stuck on one particular example. The books code and github copy differ.. but I think I am now very close to what the author meant, but now getting an error that I need help to understand where or how to solve exactly.




apples compiler gives the following... but my buddy states this compiled in GCC.. should I just stop using Apples CLANG altogether? I was hoping it was usable at least for development to get started

Thank you!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
sh compile.sh
-- Conan: Adjusting output directories
-- Conan: Using cmake targets configuration
-- Conan: Adjusting default RPATHs Conan policies
-- Conan: Adjusting language standard
-- Current conanbuildinfo.cmake directory: ch09_02_threadpool_func_wrap/build
-- Configuring done
-- Generating done
-- Build files have been written to: ch09_02_threadpool_func_wrap/build
Scanning dependencies of target test_cpp_multi
[ 33%] Building CXX object CMakeFiles/test_cpp_multi.dir/src/helloworld.cpp.o
In file included from ch09_02_threadpool_func_wrap/src/helloworld.cpp:13:
ch09_02_threadpool_func_wrap/src/thread_safe_queue.cpp:28:19: error: object of type 'function_wrapper' cannot be assigned because its copy assignment operator is implicitly deleted
            value = queue.front();
                  ^
ch09_02_threadpool_func_wrap/src/helloworld.cpp:137:16: note: in instantiation of member function 'thread_safe_queue<function_wrapper>::wait_and_pop' requested here
template class thread_safe_queue<function_wrapper>;
               ^
ch09_02_threadpool_func_wrap/src/helloworld.cpp:39:5: note: copy assignment operator is implicitly deleted because 'function_wrapper' has a user-declared move constructor
    function_wrapper(function_wrapper&& other): impl(std::move(other.impl))
    ^
In file included from ch09_02_threadpool_func_wrap/src/helloworld.cpp:13:
ch09_02_threadpool_func_wrap/src/thread_safe_queue.cpp:46:19: error: object of type 'function_wrapper' cannot be assigned because its copy assignment operator is implicitly deleted
            value = queue.front();
                  ^
ch09_02_threadpool_func_wrap/src/helloworld.cpp:137:16: note: in instantiation of member function 'thread_safe_queue<function_wrapper>::try_pop' requested here
template class thread_safe_queue<function_wrapper>;
               ^
ch09_02_threadpool_func_wrap/src/helloworld.cpp:39:5: note: copy assignment operator is implicitly deleted because 'function_wrapper' has a user-declared move constructor
    function_wrapper(function_wrapper&& other): impl(std::move(other.impl))
    ^
In file included from ch09_02_threadpool_func_wrap/src/helloworld.cpp:13:
ch09_02_threadpool_func_wrap/src/thread_safe_queue.cpp:56:41: error: no matching constructor for initialization of 'std::shared_ptr<std::mutex>'
            std::shared_ptr<std::mutex> res{std::make_shared<T>(queue.front())};
                                        ^  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ch09_02_threadpool_func_wrap/src/helloworld.cpp:137:16: note: in instantiation of member function 'thread_safe_queue<function_wrapper>::try_pop' requested here
template class thread_safe_queue<function_wrapper>;
               ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:3654:23: note: candidate constructor not viable: no known conversion from 'typename enable_if<!is_array<function_wrapper>::value, shared_ptr<function_wrapper> >::type'
      (aka 'std::__1::shared_ptr<function_wrapper>') to 'std::nullptr_t' (aka 'nullptr_t') for 1st argument
    _LIBCPP_CONSTEXPR shared_ptr(nullptr_t) _NOEXCEPT;
                      ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:3668:5: note: candidate constructor not viable: no known conversion from 'shared_ptr<function_wrapper>' to 'const shared_ptr<std::__1::mutex>' for 1st argument
    shared_ptr(const shared_ptr& __r) _NOEXCEPT;
    ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:3676:5: note: candidate constructor not viable: no known conversion from 'shared_ptr<function_wrapper>' to 'shared_ptr<std::__1::mutex>' for 1st argument
    shared_ptr(shared_ptr&& __r) _NOEXCEPT;
    ^
... etc etc


Last edited on

thread_safe_queue.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#include <mutex>
#include <memory>
#include <condition_variable>
#include <queue>

template <typename T>
class thread_safe_queue {
    public:
        // constructor
        thread_safe_queue() {}
        thread_safe_queue(const thread_safe_queue& other)
        {
            std::lock_guard<std::mutex> lock{other.mutex};
            queue = other.queue;
        }

        void push(T new_value)
        {
            std::lock_guard<std::mutex> lock{mutex};
            queue.push(new_value);
            cond.notify_one();
        }

        void wait_and_pop(T& value)
        {
            std::unique_lock<std::mutex> lock{mutex};
            cond.wait(lock, [this]{ return !queue.empty(); });
            value = queue.front();
            queue.pop();
        }

        std::shared_ptr<T> wait_and_pop()
        {
            std::unique_lock<std::mutex> lock{mutex};
            cond.wait(lock, [this]{ return !queue.empty(); });
            std::shared_ptr<T> res{std::make_shared<T>(queue.front())};
            queue.pop();
            return res;
        }

        bool try_pop(T& value)
        {
            std::lock_guard<std::mutex> lock{mutex};
            if (queue.empty())
                return false;
            value = queue.front();
            queue.pop();
            return true;
        }

        std::shared_ptr<T> try_pop()
        {
            std::lock_guard<std::mutex> lock{mutex};
            if (queue.empty())
                return std::shared_ptr<T>{};
            std::shared_ptr<std::mutex> res{std::make_shared<T>(queue.front())};
            queue.pop();
            return res;
        }

        bool empty() const
        {
            std::lock_guard<std::mutex> lock{mutex};
            return queue.empty();
        }

    private:
        mutable std::mutex mutex;
        std::condition_variable cond;
        std::queue<T> queue;
};


//https://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file
helloworld.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#include <thread>
#include <vector>
#include <atomic>
#include <iostream>
#include <future>
#include <functional>

#include <unistd.h>

 // https://github.com/anthonywilliams/ccia_code_samples/blob/6e7ae1d66dbd2e8f1ad18a5cf5c6d25a37b92388/listings/listing_9.1.cpp
 // https://github.com/anthonywilliams/ccia_code_samples/blob/6e7ae1d66dbd2e8f1ad18a5cf5c6d25a37b92388/listings/listing_9.2.cpp

#include "thread_safe_queue.cpp"

class function_wrapper
{
    struct impl_base {
        virtual void call()=0;
        virtual ~impl_base() {}
    };
    std::unique_ptr<impl_base> impl;
    template<typename F>
    struct impl_type: impl_base
    {
        F f;
        impl_type(F&& f_): f(std::move(f_)) {}
        void call() { f(); }
    };
public:
    template<typename F>
    function_wrapper(F&& f): impl(new impl_type<F>(std::move(f)))
    {}

    //void call() { impl->call(); }
    void operator()(){ impl->call(); }

    function_wrapper() = default;

    function_wrapper(function_wrapper&& other): impl(std::move(other.impl))
    {}

    function_wrapper& operator=(function_wrapper&& other)
    {
        impl=std::move(other.impl);
        return *this;
    }

    function_wrapper(const function_wrapper&)=delete;
    function_wrapper(function_wrapper&)=delete;
    function_wrapper& operator=(const function_wrapper&)=delete;
};

struct join_threads
{
    join_threads(std::vector<std::thread>&)
    {}
};

class thread_pool
{
    std::atomic_bool done;
    thread_safe_queue<function_wrapper> work_queue;
    std::vector<std::thread> threads;
    join_threads joiner;

    void worker_thread()
    {
        while(!done)
        {
            function_wrapper task;
            if(work_queue.try_pop(task))
            {
                task();
            }
            else
            {
                std::this_thread::yield();
            }
        }
    }
public:
    thread_pool():
        done(false),joiner(threads)
    {
        unsigned const thread_count=std::thread::hardware_concurrency();
        try
        {
            for(unsigned i=0;i<thread_count;++i)
            {
                threads.push_back(
                    std::thread(&thread_pool::worker_thread,this));
            }
        }
        catch(...)
        {
            done=true;
            throw;
        }
    }

    ~thread_pool()
    {
        done=true;
    }

    template<typename FunctionType>
    std::future<typename std::result_of<FunctionType()>::type> submit(FunctionType f)
    {
        typedef typename std::result_of<FunctionType()>::type result_type;
        
        std::packaged_task<result_type()> task(std::move(f));
        std::future<result_type> res(task.get_future());
        work_queue.push(std::move(task));
        return res;
    }
};

void find_the_answer_to_ltuae(){
    std::cout << "About to sleep 1 second...";
    sleep(1);
    std::cout<<"The answer is " << 42 << std::endl;
}

int main()
{
    std::cout << "About to create my_threadpool...." << std::endl;
    thread_pool my_threadpool;
    std::cout << "Done creating my_threadpool...." << std::endl;
    std::cout << "Submitting first job now" << std::endl;
    my_threadpool.submit(find_the_answer_to_ltuae);
    sleep(10);
    std::cout <<"Finished" << std::endl;
}

//https://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file

template class thread_safe_queue<function_wrapper>;


got setup with GCC in an attempt to test a different setup... same result so, it's not apple

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
-- Conan: Adjusting output directories
-- Conan: Using cmake targets configuration
-- Conan: Adjusting default RPATHs Conan policies
-- Conan: Adjusting language standard
-- Current conanbuildinfo.cmake directory: /ch09_02_threadpool_func_wrap/build
-- Conan: Compiler GCC>=5, checking major version 9
-- Conan: Checking correct version: 9
-- Configuring done
-- Generating done
-- Build files have been written to: /ch09_02_threadpool_func_wrap/build
[ 33%] Building CXX object CMakeFiles/test_cpp_multi.dir/src/helloworld.cpp.o
In file included from /ch09_02_threadpool_func_wrap/src/helloworld.cpp:13:
/ch09_02_threadpool_func_wrap/src/thread_safe_queue.cpp: In instantiation of ‘bool thread_safe_queue<T>::try_pop(T&) [with T = function_wrapper]’:
/ch09_02_threadpool_func_wrap/src/helloworld.cpp:71:39:   required from here
/ch09_02_threadpool_func_wrap/src/thread_safe_queue.cpp:46:19: error: use of deleted function ‘function_wrapper& function_wrapper::operator=(const function_wrapper&)’
   46 |             value = queue.front();
/ch09_02_threadpool_func_wrap/src/helloworld.cpp:50:23: note: declared here
   50 |     function_wrapper& operator=(const function_wrapper&)=delete;
      |                       ^~~~~~~~
In file included from /ch09_02_threadpool_func_wrap/src/helloworld.cpp:13:
/ch09_02_threadpool_func_wrap/src/thread_safe_queue.cpp: In instantiation of ‘void thread_safe_queue<T>::wait_and_pop(T&) [with T = function_wrapper]’:
/ch09_02_threadpool_func_wrap/src/helloworld.cpp:137:16:   required from here
/ch09_02_threadpool_func_wrap/src/thread_safe_queue.cpp:28:19: error: use of deleted function ‘function_wrapper& function_wrapper::operator=(const function_wrapper&)’
   28 |             value = queue.front();
/ch09_02_threadpool_func_wrap/src/helloworld.cpp:50:23: note: declared here
   50 |     function_wrapper& operator=(const function_wrapper&)=delete;
      |                       ^~~~~~~~
In file included from /ch09_02_threadpool_func_wrap/src/helloworld.cpp:13:
/ch09_02_threadpool_func_wrap/src/thread_safe_queue.cpp: In instantiation of ‘std::shared_ptr<_Tp> thread_safe_queue<T>::try_pop() [with T = function_wrapper]’:
/ch09_02_threadpool_func_wrap/src/helloworld.cpp:137:16:   required from here
/ch09_02_threadpool_func_wrap/src/thread_safe_queue.cpp:56:41: error: no matching function for call to ‘std::shared_ptr<std::mutex>::shared_ptr(<brace-enclosed initializer list>)’
   56 |             std::shared_ptr<std::mutex> res{std::make_shared<T>(queue.front())};
      |                                         ^~~
In file included from /usr/include/c++/9/memory:81,
                 from /usr/include/c++/9/thread:39,
                 from /ch09_02_threadpool_func_wrap/src/helloworld.cpp:1:
/usr/include/c++/9/bits/shared_ptr.h:367:7: note: candidate: ‘std::shared_ptr<_Tp>::shared_ptr(const std::weak_ptr<_Tp>&, std::nothrow_t) [with _Tp = std::mutex]’
  367 |       shared_ptr(const weak_ptr<_Tp>& __r, std::nothrow_t)
      |       ^~~~~~~~~~
/usr/include/c++/9/bits/shared_ptr.h:367:7: note:   candidate expects 2 arguments, 1 provided
/usr/include/c++/9/bits/shared_ptr.h:358:2: note: candidate: ‘template<class _Alloc, class ... _Args> std::shared_ptr<_Tp>::shared_ptr(std::_Sp_alloc_shared_tag<_Tp>, _Args&& ...)’
  358 |  shared_ptr(_Sp_alloc_shared_tag<_Alloc> __tag, _Args&&... __args)
      |  ^~~~~~~~~~
/usr/include/c++/9/bits/shared_ptr.h:358:2: note:   template argument deduction/substitution failed:
In file included from /ch09_02_threadpool_func_wrap/src/helloworld.cpp:13:
/ch09_02_threadpool_func_wrap/src/thread_safe_queue.cpp:56:41: note:   ‘std::shared_ptr<function_wrapper>’ is not derived from ‘std::_Sp_alloc_shared_tag<_Tp>’
   56 |             std::shared_ptr<std::mutex> res{std::make_shared<T>(queue.front())};
      |                                         ^~~
In file included from /usr/include/c++/9/memory:81,
                 from /usr/include/c++/9/thread:39,
                 from /ch09_02_threadpool_func_wrap/src/helloworld.cpp:1:
/usr/include/c++/9/bits/shared_ptr.h:307:17: note: candidate: ‘constexpr std::shared_ptr<_Tp>::shared_ptr(std::nullptr_t) [with _Tp = std::mutex; std::nullptr_t = std::nullptr_t]’
  307 |       constexpr shared_ptr(nullptr_t) noexcept : shared_ptr() { }
      |                 ^~~~~~~~~~
/usr/include/c++/9/bits/shared_ptr.h:307:28: note:   no known conversion for argument 1 from ‘std::shared_ptr<function_wrapper>’ to ‘std::nullptr_t’
  307 |       constexpr shared_ptr(nullptr_t) noexcept : shared_ptr() { }
      |                            ^~~~~~~~~
/usr/include/c++/9/bits/shared_ptr.h:299:2: note: candidate: ‘template<class _Yp, class _Del, std::shared_ptr<std::mutex>::_Constructible<std::unique_ptr<_Tp, _Dp>, std::__sp_array_delete>* <anonymous> > std::shared_ptr<_Tp>::shared_ptr(std::unique_ptr<_Up, _Ep>&&)’
  299 |  shared_ptr(unique_ptr<_Yp, _Del>&& __r)
      |  ^~~~~~~~~~
/usr/include/c++/9/bits/shared_ptr.h:299:2: note:   template argument deduction/substitution failed:
In file included from /ch09_02_threadpool_func_wrap/src/helloworld.cpp:13:
/ch09_02_threadpool_func_wrap/src/thread_safe_queue.cpp:56:41: note:   ‘std::shared_ptr<function_wrapper>’ is not derived from ‘std::unique_ptr<_Tp, _Dp>’
   56 |             std::shared_ptr<std::mutex> res{std::make_shared<T>(queue.front())};
      |                                         ^~~
In file included from /usr/include/c++/9/memory:81,
                 from /usr/include/c++/9/thread:39,
                 from /ch09_02_threadpool_func_wrap/src/helloworld.cpp:1:
/usr/include/c++/9/bits/shared_ptr.h:290:2: note: candidate: ‘template<class _Yp, class _Del, class> std::shared_ptr<_Tp>::shared_ptr(std::unique_ptr<_Up, _Ep>&&)’
  290 |  shared_ptr(unique_ptr<_Yp, _Del>&& __r)
      |  ^~~~~~~~~~
/usr/include/c++/9/bits/shared_ptr.h:290:2: note:   template argument deduction/substitution failed:
In file included from /ch09_02_threadpool_func_wrap/src/helloworld.cpp:13:
/ch09_02_threadpool_func_wrap/src/thread_safe_queue.cpp:56:41: note:   ‘std::shared_ptr<function_wrapper>’ is not derived from ‘std::unique_ptr<_Tp, _Dp>’
   56 |             std::shared_ptr<std::mutex> res{std::make_shared<T>(queue.front())};
      |                                         ^~~
In file included from /usr/include/c++/9/memory:81,
                 from /usr/include/c++/9/thread:39,
                 from /ch09_02_threadpool_func_wrap/src/helloworld.cpp:1:
/usr/include/c++/9/bits/shared_ptr.h:282:2: note: candidate: ‘template<class _Yp, class> std::shared_ptr<_Tp>::shared_ptr(std::auto_ptr<_Up>&&)’
  282 |  shared_ptr(auto_ptr<_Yp>&& __r);
      |  ^~~~~~~~~~
/usr/include/c++/9/bits/shared_ptr.h:282:2: note:   template argument deduction/substitution failed:
In file included from /ch09_02_threadpool_func_wrap/src/helloworld.cpp:13:
/ch09_02_threadpool_func_wrap/src/thread_safe_queue.cpp:56:41: note:   ‘std::shared_ptr<function_wrapper>’ is not derived from ‘std::auto_ptr<_Up>’
   56 |             std::shared_ptr<std::mutex> res{std::make_shared<T>(queue.front())};
      |                                         ^~~
In file included from /usr/include/c++/9/memory:81,
Just to try to summarize what the compiler is saying:

You have:
thread_safe_queue<function_wrapper> work_queue;

You attempt to call:
1
2
           function_wrapper task;
           if (work_queue.try_pop(task))


Inside, try_pop, you do:
1
2
3
4
5
bool try_pop(T& value)
{
    value = queue.front();
    // ...
}

where T = function_wrapper.

The issue is that you deleted the assignment operator,
function_wrapper& operator=(const function_wrapper&)=delete;
so you can't call value = queue.front().

I know this isn't a solution to your problem, but that appears to be the issue.
Where does the github and the book differ? Which version are you trying to compile? I would expect errata to be fixed on github if it existed. And, what version of GCC was your friend trying to use?
Last edited on
I looked up the code online, and there is a key difference that you appear to be missing
1
2
3
4
5
6
7
8
9
10
11
    bool try_pop(data_type& res)
    {
        std::lock_guard<std::mutex> lock(the_mutex);
        if(the_queue.empty())
        {
            return false;
        }
        res=std::move(the_queue.front());
        the_queue.pop_front();
        return true;
    }

Notice the std::move there. That transforms the T& into a T&&, allowing it to use the move-assignment operator, which is safe as long as pop_front() is immediately called before anything else can access the queue.
Last edited on
Thanks Ganado..

The book and github do not differ whatsoever in that area you highlight.. and indeed I am learning about about the compilers templating system.. and commented out ALL the `=delete;` lines.. only 1 of the 7-8 errors went away then

the book had some correct looking pieces in the function_wrapper (see what was commented out)

1
2
3
4
5
6
7
public:
    template<typename F>
    function_wrapper(F&& f): impl(new impl_type<F>(std::move(f)))
    {}

    //void call() { impl->call(); }    <------this was in the github version, didnt work
    void operator()(){ impl->call(); }


The github version also dropped the self-authored thread_safe_queue .. and switched to a "double queue" from the std library...

1
2
3
4
5
6
class thread_pool
{
public:
    std::deque<function_wrapper> work_queue; // <----------------this becomes a deque on github

    template<typename FunctionType>


I've posted to the repo in attempt to get some assistance but it looks a bit quiet there.. URL is in the code comments here.

https://github.com/anthonywilliams/ccia_code_samples/blob/6e7ae1d66dbd2e8f1ad18a5cf5c6d25a37b92388/listings/listing_9.1.cpp
https://github.com/anthonywilliams/ccia_code_samples/blob/6e7ae1d66dbd2e8f1ad18a5cf5c6d25a37b92388/listings/listing_9.2.cpp

I will check my friends setup tomorrow.. good call

I am on Ubuntu with gcc 9.3.0
I am on MacOS with
1
2
3
4
5
6
clang --version
Apple clang version 12.0.0 (clang-1200.0.32.28)
Target: x86_64-apple-darwin20.2.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin



reason I hesitate regarding using the std::deque .. is simply I am trying to learn about thread safety... how to write code that works in a concurrent manner.. and unsure if I am going to be able to follow the rest of the chapters examples without that thread_safe_queue class
Last edited on
Regarding @Ganado , your insight on the T=function_wrapper part...

what if I implement a non-templated version of this class?? so instead of

1
2
3
4
5
6
        void push(T new_value)
        {
            std::lock_guard<std::mutex> lock{mutex};
            queue.push(new_value);
            cond.notify_one();
        }


try to write the class JUST for `function_wrapper` so that

1
2
3
4
5
6
        void push(function_wrapper new_value)
        {
            std::lock_guard<std::mutex> lock{mutex};
            queue.push(new_value);  //< ---- maybe switch this to passing the...pointer ?   not sure what techniques to try here
            cond.notify_one();
        }
Last edited on
Update, thank you Ganado... I spoke to my friend.. turns out he was looking at another directory in my working repo... he now likely will get the same output as I am...

back to your suggestions, I somehow missed your insight on the `try_pop` missing a `std::move()` .. I went ahead an added the needed move, but it still complains. I am going to look at the github version again.. and perhaps make another directory copy of this project and retry with the `deque`


now thread_safe_queue.cpp contains the following

1
2
3
4
5
6
7
8
9
        bool try_pop(T& value)
        {
            std::lock_guard<std::mutex> lock{mutex};
            if (queue.empty())
                return false;
            value = std::move(queue.front());
            queue.pop();
            return true;
        }


resulting output of compiler

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
(base) emcp@EMCPs-Mac-mini ch09_02_threadpool_func_wrap % sh compile.sh
-- Conan: Adjusting output directories
-- Conan: Using cmake targets configuration
-- Conan: Adjusting default RPATHs Conan policies
-- Conan: Adjusting language standard
-- Current conanbuildinfo.cmake directory: /Users/emcp/Dev/git/EMCP/cpp-multithreading-in-action/ch09_02_threadpool_func_wrap/build
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/emcp/Dev/git/EMCP/cpp-multithreading-in-action/ch09_02_threadpool_func_wrap/build
[ 33%] Building CXX object CMakeFiles/test_cpp_multi.dir/src/helloworld.cpp.o
In file included from /Users/emcp/Dev/git/EMCP/cpp-multithreading-in-action/ch09_02_threadpool_func_wrap/src/helloworld.cpp:13:
/Users/emcp/Dev/git/EMCP/cpp-multithreading-in-action/ch09_02_threadpool_func_wrap/src/thread_safe_queue.cpp:28:19: error: overload resolution selected deleted operator '='
            value = queue.front();
            ~~~~~ ^ ~~~~~~~~~~~~~
/Users/emcp/Dev/git/EMCP/cpp-multithreading-in-action/ch09_02_threadpool_func_wrap/src/helloworld.cpp:137:16: note: in instantiation of member function 'thread_safe_queue<function_wrapper>::wait_and_pop' requested here
template class thread_safe_queue<function_wrapper>;
               ^
/Users/emcp/Dev/git/EMCP/cpp-multithreading-in-action/ch09_02_threadpool_func_wrap/src/helloworld.cpp:50:23: note: candidate function has been explicitly deleted
    function_wrapper& operator=(const function_wrapper&)=delete;
                      ^
/Users/emcp/Dev/git/EMCP/cpp-multithreading-in-action/ch09_02_threadpool_func_wrap/src/helloworld.cpp:42:23: note: candidate function not viable: no known conversion from 'std::__1::__deque_base<function_wrapper, std::__1::allocator<function_wrapper> >::value_type' (aka 'function_wrapper') to
      'function_wrapper &&' for 1st argument
    function_wrapper& operator=(function_wrapper&& other)
                      ^
In file included from /Users/emcp/Dev/git/EMCP/cpp-multithreading-in-action/ch09_02_threadpool_func_wrap/src/helloworld.cpp:13:
/Users/emcp/Dev/git/EMCP/cpp-multithreading-in-action/ch09_02_threadpool_func_wrap/src/thread_safe_queue.cpp:56:41: error: no matching constructor for initialization of 'std::shared_ptr<std::mutex>'
            std::shared_ptr<std::mutex> res{std::make_shared<T>(queue.front())};
                                        ^  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/Users/emcp/Dev/git/EMCP/cpp-multithreading-in-action/ch09_02_threadpool_func_wrap/src/helloworld.cpp:137:16: note: in instantiation of member function 'thread_safe_queue<function_wrapper>::try_pop' requested here
template class thread_safe_queue<function_wrapper>;
               ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:3654:23: note: candidate constructor not viable: no known conversion from 'typename enable_if<!is_array<function_wrapper>::value, shared_ptr<function_wrapper> >::type'
      (aka 'std::__1::shared_ptr<function_wrapper>') to 'std::nullptr_t' (aka 'nullptr_t') for 1st argument
    _LIBCPP_CONSTEXPR shared_ptr(nullptr_t) _NOEXCEPT;
                      ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:3668:5: note: candidate constructor not viable: no known conversion from 'shared_ptr<function_wrapper>' to 'const shared_ptr<std::__1::mutex>' for 1st argument
    shared_ptr(const shared_ptr& __r) _NOEXCEPT;
    ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:3676:5: note: candidate constructor not viable: no known conversion from 'shared_ptr<function_wrapper>' to 'shared_ptr<std::__1::mutex>' for 1st argument
    shared_ptr(shared_ptr&& __r) _NOEXCEPT;
    ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:3656:18: note: candidate template ignored: could not match '_Yp *' against 'typename enable_if<!is_array<function_wrapper>::value, shared_ptr<function_wrapper> >::type'
      (aka 'std::__1::shared_ptr<function_wrapper>')
        explicit shared_ptr(_Yp* __p,
                 ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:3671:9: note: candidate template ignored: requirement 'is_convertible<function_wrapper *, std::__1::mutex *>::value' was not satisfied [with _Yp = function_wrapper]
        shared_ptr(const shared_ptr<_Yp>& __r,
        ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:3677:52: note: candidate template ignored: requirement 'is_convertible<function_wrapper *, std::__1::mutex *>::value' was not satisfied [with _Yp = function_wrapper]
    template<class _Yp> _LIBCPP_INLINE_VISIBILITY  shared_ptr(shared_ptr<_Yp>&& __r,
                                                   ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:3681:34: note: candidate template ignored: could not match 'weak_ptr' against 'shared_ptr'
    template<class _Yp> explicit shared_ptr(const weak_ptr<_Yp>& __r,
                                 ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:3686:9: note: candidate template ignored: could not match 'auto_ptr' against 'shared_ptr'
        shared_ptr(auto_ptr<_Yp>&& __r,
        ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:3696:9: note: candidate template ignored: could not match 'unique_ptr' against 'shared_ptr'
        shared_ptr(unique_ptr<_Yp, _Dp>&&,
        ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:3705:9: note: candidate template ignored: could not match 'unique_ptr' against 'shared_ptr'
        shared_ptr(unique_ptr<_Yp, _Dp>&&,
        ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:3659:9: note: candidate constructor template not viable: requires at least 2 arguments, but 1 was provided
        shared_ptr(_Yp* __p, _Dp __d,
        ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:3662:9: note: candidate constructor template not viable: requires at least 3 arguments, but 1 was provided
        shared_ptr(_Yp* __p, _Dp __d, _Alloc __a,
        ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:3664:26: note: candidate constructor template not viable: requires 2 arguments, but 1 was provided
    template <class _Dp> shared_ptr(nullptr_t __p, _Dp __d);
                         ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:3665:40: note 

and on and on
The code might have been designed against an outdated standard library which does not implement LWG2067.
https://wg21.link/lwg2067

There are a few further problems, but the lack of a copy-constructor (not defined as deleted) for packaged_task is the most important.
Last edited on
Topic archived. No new replies allowed.