Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does std::condition_variable as a class member cause compile errors with std::thread?

I tried including std::condition_variable as a class member, and got a lot of compilation errors when passing an object of this class to a std::thread. I cut down all the other code from my actual program, and ended up with the below minimal code. Removing the std::condition_variable causes no problems. I tried "initializing" the variable in the constructor, as well as making it inline, but neither helped.

#include <thread>
#include <condition_variable>

struct ThreadHandler {
    void operator()() { }

    std::condition_variable cond; 
};

int main() {
    ThreadHandler th1;
    std::thread t1(th1);
    t1.join(); 
}

What am I doing wrong here?

Below is the compilation error I get:

In file included from main.cpp:1:
/usr/local/include/c++/8.1.0/thread: In instantiation of ‘static std::thread::_Invoker<std::tuple<typename std::decay<_Tp>::type, typename std::decay<_Args>::type ...> > std::thread::__make_invoker(_Callable&&, _Args&& ...) [with _Callable = ThreadHandler&; _Args = {}; typename std::decay<_Tp>::type = ThreadHandler]’:
/usr/local/include/c++/8.1.0/thread:127:22:   required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = ThreadHandler&; _Args = {}]’
main.cpp:14:23:   required from here
/usr/local/include/c++/8.1.0/thread:258:4: error: no matching function for call to ‘std::tuple<ThreadHandler>::tuple(<brace-enclosed initializer list>)’
  } };
    ^
In file included from /usr/local/include/c++/8.1.0/bits/unique_ptr.h:37,
                 from /usr/local/include/c++/8.1.0/memory:80,
                 from /usr/local/include/c++/8.1.0/thread:39,
                 from main.cpp:1:
/usr/local/include/c++/8.1.0/tuple:828:11: note: candidate: ‘template<class _Alloc, class _Dummy, class ... _UElements, typename std::enable_if<((std::_TC<((1 == sizeof... (_UElements)) && (! std::is_same<std::tuple<ThreadHandler>, std::tuple<_Tail ...> >::value)), ThreadHandler>::_MoveConstructibleTuple<_UElements ...>() && (! std::_TC<((1 == sizeof... (_UElements)) && (! std::is_same<std::tuple<ThreadHandler>, std::tuple<_Tail ...> >::value)), ThreadHandler>::_ImplicitlyMoveConvertibleTuple<_UElements ...>())) && std::_TC<(std::is_same<_Dummy, void>::value && (1 == 1)), ThreadHandler>::_NonNestedTuple<tuple<_Tail ...>&&>()), bool>::type <anonymous> > std::tuple<_Elements>::tuple(std::allocator_arg_t, const _Alloc&, std::tuple<_Args2 ...>&&)’
  explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
           ^~~~~
/usr/local/include/c++/8.1.0/tuple:828:11: note:   template argument deduction/substitution failed:
In file included from main.cpp:1:
/usr/local/include/c++/8.1.0/thread:258:4: note:   candidate expects 3 arguments, 1 provided
  } };
    ^
In file included from /usr/local/include/c++/8.1.0/bits/unique_ptr.h:37,
                 from /usr/local/include/c++/8.1.0/memory:80,
                 from /usr/local/include/c++/8.1.0/thread:39,
                 from main.cpp:1:
/usr/local/include/c++/8.1.0/tuple:813:2: note: candidate: ‘template<class _Alloc, class _Dummy, class ... _UElements, typename std::enable_if<((std::_TC<((1 == sizeof... (_UElements)) && (! std::is_same<std::tuple<ThreadHandler>, std::tuple<_Tail ...> >::value)), ThreadHandler>::_MoveConstructibleTuple<_UElements ...>() && std::_TC<((1 == sizeof... (_UElements)) && (! std::is_same<std::tuple<ThreadHandler>, std::tuple<_Tail ...> >::value)), ThreadHandler>::_ImplicitlyMoveConvertibleTuple<_UElements ...>()) && std::_TC<(std::is_same<_Dummy, void>::value && (1 == 1)), ThreadHandler>::_NonNestedTuple<tuple<_Tail ...>&&>()), bool>::type <anonymous> > std::tuple<_Elements>::tuple(std::allocator_arg_t, const _Alloc&, std::tuple<_Args2 ...>&&)’
  tuple(allocator_arg_t __tag, const _Alloc& __a,
  ^~~~~
/usr/local/include/c++/8.1.0/tuple:813:2: note:   template argument deduction/substitution failed:
In file included from main.cpp:1:
/usr/local/include/c++/8.1.0/thread:258:4: note:   candidate expects 3 arguments, 1 provided
  } };
    ^
In file included from /usr/local/include/c++/8.1.0/bits/unique_ptr.h:37,
                 from /usr/local/include/c++/8.1.0/memory:80,
                 from /usr/local/include/c++/8.1.0/thread:39,
                 from main.cpp:1:
/usr/local/include/c++/8.1.0/tuple:798:11: note: candidate: ‘template<class _Alloc, class _Dummy, class ... _UElements, typename std::enable_if<((std::_TC<((1 == sizeof... (_UElements)) && (! std::is_same<std::tuple<ThreadHandler>, std::tuple<_Tail ...> >::value)), ThreadHandler>::_ConstructibleTuple<_UElements ...>() && (! std::_TC<((1 == sizeof... (_UElements)) && (! std::is_same<std::tuple<ThreadHandler>, std::tuple<_Tail ...> >::value)), ThreadHandler>::_ImplicitlyConvertibleTuple<_UElements ...>())) && std::_TC<(std::is_same<_Dummy, void>::value && (1 == 1)), ThreadHandler>::_NonNestedTuple<tuple<_Tail ...>&&>()), bool>::type <anonymous> > std::tuple<_Elements>::tuple(std::allocator_arg_t, const _Alloc&, const std::tuple<_Args2 ...>&)’
  explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
           ^~~~~
/usr/local/include/c++/8.1.0/tuple:798:11: note:   template argument deduction/substitution failed:
In file included from main.cpp:1:
/usr/local/include/c++/8.1.0/thread:258:4: note:   candidate expects 3 arguments, 1 provided
  } };
    ^
In file included from /usr/local/include/c++/8.1.0/bits/unique_ptr.h:37,
                 from /usr/local/include/c++/8.1.0/memory:80,
                 from /usr/local/include/c++/8.1.0/thread:39,
                 from main.cpp:1:
/usr/local/include/c++/8.1.0/tuple:783:2: note: candidate: ‘template<class _Alloc, class _Dummy, class ... _UElements, typename std::enable_if<((std::_TC<((1 == sizeof... (_UElements)) && (! std::is_same<std::tuple<ThreadHandler>, std::tuple<_Tail ...> >::value)), ThreadHandler>::_ConstructibleTuple<_UElements ...>() && std::_TC<((1 == sizeof... (_UElements)) && (! std::is_same<std::tuple<ThreadHandler>, std::tuple<_Tail ...> >::value)), ThreadHandler>::_ImplicitlyConvertibleTuple<_UElements ...>()) && std::_TC<(std::is_same<_Dummy, void>::value && (1 == 1)), ThreadHandler>::_NonNestedTuple<tuple<_Tail ...>&&>()), bool>::type <anonymous> > std::tuple<_Elements>::tuple(std::allocator_arg_t, const _Alloc&, const std::tuple<_Args2 ...>&)’
  tuple(allocator_arg_t __tag, const _Alloc& __a,
  ^~~~~
/usr/local/include/c++/8.1.0/tuple:783:2: note:   template argument deduction/substitution failed:
In file included from main.cpp:1:
/usr/local/include/c++/8.1.0/thread:258:4: note:   candidate expects 3 arguments, 1 provided
  } };
    ^
In file included from /usr/local/include/c++/8.1.0/bits/unique_ptr.h:37,
                 from /usr/local/include/c++/8.1.0/memory:80,
                 from /usr/local/include/c++/8.1.0/thread:39,
                 from main.cpp:1:
/usr/local/include/c++/8.1.0/tuple:771:2: note: candidate: ‘template<class _Alloc> std::tuple<_Elements>::tuple(std::allocator_arg_t, const _Alloc&, std::tuple<_Elements>&&)’
  tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in)
  ^~~~~
/usr/local/include/c++/8.1.0/tuple:771:2: note:   template argument deduction/substitution failed:
In file included from main.cpp:1:
/usr/local/include/c++/8.1.0/thread:258:4: note:   candidate expects 3 arguments, 1 provided
  } };
    ^
In file included from /usr/local/include/c++/8.1.0/bits/unique_ptr.h:37,
                 from /usr/local/include/c++/8.1.0/memory:80,
                 from /usr/local/include/c++/8.1.0/thread:39,
                 from main.cpp:1:
/usr/local/include/c++/8.1.0/tuple:767:2: note: candidate: ‘template<class _Alloc> std::tuple<_Elements>::tuple(std::allocator_arg_t, const _Alloc&, const std::tuple<_Elements>&)’
  tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in)
  ^~~~~
/usr/local/include/c++/8.1.0/tuple:767:2: note:   template argument deduction/substitution failed:
In file included from main.cpp:1:
/usr/local/include/c++/8.1.0/thread:258:4: note:   candidate expects 3 arguments, 1 provided
  } };
    ^
In file included from /usr/local/include/c++/8.1.0/bits/unique_ptr.h:37,
                 from /usr/local/include/c++/8.1.0/memory:80,
                 from /usr/local/include/c++/8.1.0/thread:39,
                 from main.cpp:1:
/usr/local/include/c++/8.1.0/tuple:761:11: note: candidate: ‘template<class _Alloc, class ... _UElements, typename std::enable_if<(std::_TC<((1 == sizeof... (_UElements)) && std::_TC<(sizeof... (_UElements) == 1), ThreadHandler>::_NotSameTuple<_UElements ...>()), ThreadHandler>::_MoveConstructibleTuple<_UElements ...>() && (! std::_TC<((1 == sizeof... (_UElements)) && std::_TC<(sizeof... (_UElements) == 1), ThreadHandler>::_NotSameTuple<_UElements ...>()), ThreadHandler>::_ImplicitlyMoveConvertibleTuple<_UElements ...>())), bool>::type <anonymous> > std::tuple<_Elements>::tuple(std::allocator_arg_t, const _Alloc&, _UElements&& ...)’
  explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
           ^~~~~
/usr/local/include/c++/8.1.0/tuple:761:11: note:   template argument deduction/substitution failed:
In file included from main.cpp:1:
/usr/local/include/c++/8.1.0/thread:258:4: note:   candidate expects at least 2 arguments, 1 provided
  } };
    ^
In file included from /usr/local/include/c++/8.1.0/bits/unique_ptr.h:37,
                 from /usr/local/include/c++/8.1.0/memory:80,
                 from /usr/local/include/c++/8.1.0/thread:39,
                 from main.cpp:1:
/usr/local/include/c++/8.1.0/tuple:750:2: note: candidate: ‘template<class _Alloc, class ... _UElements, typename std::enable_if<(std::_TC<((1 == sizeof... (_UElements)) && std::_TC<(sizeof... (_UElements) == 1), ThreadHandler>::_NotSameTuple<_UElements ...>()), ThreadHandler>::_MoveConstructibleTuple<_UElements ...>() && std::_TC<((1 == sizeof... (_UElements)) && std::_TC<(sizeof... (_UElements) == 1), ThreadHandler>::_NotSameTuple<_UElements ...>()), ThreadHandler>::_ImplicitlyMoveConvertibleTuple<_UElements ...>()), bool>::type <anonymous> > std::tuple<_Elements>::tuple(std::allocator_arg_t, const _Alloc&, _UElements&& ...)’
  tuple(allocator_arg_t __tag, const _Alloc& __a,
  ^~~~~
/usr/local/include/c++/8.1.0/tuple:750:2: note:   template argument deduction/substitution failed:
In file included from main.cpp:1:
/usr/local/include/c++/8.1.0/thread:258:4: note:   candidate expects at least 2 arguments, 1 provided
  } };
    ^
In file included from /usr/local/include/c++/8.1.0/bits/unique_ptr.h:37,
                 from /usr/local/include/c++/8.1.0/memory:80,
                 from /usr/local/include/c++/8.1.0/thread:39,
                 from main.cpp:1:
/usr/local/include/c++/8.1.0/tuple:740:11: note: candidate: ‘template<class _Alloc, class _Dummy, typename std::enable_if<(std::_TC<std::is_same<_Dummy, void>::value, ThreadHandler>::_ConstructibleTuple<ThreadHandler>() && (! std::_TC<std::is_same<_Dummy, void>::value, ThreadHandler>::_ImplicitlyConvertibleTuple<ThreadHandler>())), bool>::type <anonymous> > std::tuple<_Elements>::tuple(std::allocator_arg_t, const _Alloc&, const _Elements& ...)’
  explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
           ^~~~~
/usr/local/include/c++/8.1.0/tuple:740:11: note:   template argument deduction/substitution failed:
In file included from main.cpp:1:
/usr/local/include/c++/8.1.0/thread:258:4: note:   candidate expects 3 arguments, 1 provided
  } };
    ^
In file included from /usr/local/include/c++/8.1.0/bits/unique_ptr.h:37,
                 from /usr/local/include/c++/8.1.0/memory:80,
                 from /usr/local/include/c++/8.1.0/thread:39,
                 from main.cpp:1:
/usr/local/include/c++/8.1.0/tuple:729:2: note: candidate: ‘template<class _Alloc, class _Dummy, typename std::enable_if<(std::_TC<std::is_same<_Dummy, void>::value, ThreadHandler>::_ConstructibleTuple<ThreadHandler>() && std::_TC<std::is_same<_Dummy, void>::value, ThreadHandler>::_ImplicitlyConvertibleTuple<ThreadHandler>()), bool>::type <anonymous> > std::tuple<_Elements>::tuple(std::allocator_arg_t, const _Alloc&, const _Elements& ...)’
  tuple(allocator_arg_t __tag, const _Alloc& __a,
  ^~~~~
/usr/local/include/c++/8.1.0/tuple:729:2: note:   template argument deduction/substitution failed:
In file included from main.cpp:1:
/usr/local/include/c++/8.1.0/thread:258:4: note:   candidate expects 3 arguments, 1 provided
  } };
    ^
In file included from /usr/local/include/c++/8.1.0/bits/unique_ptr.h:37,
                 from /usr/local/include/c++/8.1.0/memory:80,
                 from /usr/local/include/c++/8.1.0/thread:39,
                 from main.cpp:1:
/usr/local/include/c++/8.1.0/tuple:719:2: note: candidate: ‘template<class _Alloc> std::tuple<_Elements>::tuple(std::allocator_arg_t, const _Alloc&)’
  tuple(allocator_arg_t __tag, const _Alloc& __a)
  ^~~~~
/usr/local/include/c++/8.1.0/tuple:719:2: note:   template argument deduction/substitution failed:
In file included from main.cpp:1:
/usr/local/include/c++/8.1.0/thread:258:4: note:   candidate expects 2 arguments, 1 provided
  } };
    ^
In file included from /usr/local/include/c++/8.1.0/bits/unique_ptr.h:37,
                 from /usr/local/include/c++/8.1.0/memory:80,
                 from /usr/local/include/c++/8.1.0/thread:39,
                 from main.cpp:1:
/usr/local/include/c++/8.1.0/tuple:713:28: note: candidate: ‘template<class ... _UElements, class _Dummy, typename std::enable_if<((std::_TC<((1 == sizeof... (_UElements)) && (! std::is_same<std::tuple<ThreadHandler>, std::tuple<_Tps ...> >::value)), ThreadHandler>::_MoveConstructibleTuple<_UElements ...>() && (! std::_TC<((1 == sizeof... (_UElements)) && (! std::is_same<std::tuple<ThreadHandler>, std::tuple<_Tps ...> >::value)), ThreadHandler>::_ImplicitlyMoveConvertibleTuple<_UElements ...>())) && std::_TC<(std::is_same<_Dummy, void>::value && (1 == 1)), ThreadHandler>::_NonNestedTuple<tuple<_Tps ...>&&>()), bool>::type <anonymous> > constexpr std::tuple<_Elements>::tuple(std::tuple<_Args1 ...>&&)’
         explicit constexpr tuple(tuple<_UElements...>&& __in)
                            ^~~~~
/usr/local/include/c++/8.1.0/tuple:713:28: note:   template argument deduction/substitution failed:
In file included from main.cpp:1:
/usr/local/include/c++/8.1.0/thread:258:4: note:   ‘ThreadHandler’ is not derived from ‘std::tuple<_Tps ...>’
  } };
    ^
In file included from /usr/local/include/c++/8.1.0/bits/unique_ptr.h:37,
                 from /usr/local/include/c++/8.1.0/memory:80,
                 from /usr/local/include/c++/8.1.0/thread:39,
                 from main.cpp:1:
/usr/local/include/c++/8.1.0/tuple:702:19: note: candidate: ‘template<class ... _UElements, class _Dummy, typename std::enable_if<((std::_TC<((1 == sizeof... (_UElements)) && (! std::is_same<std::tuple<ThreadHandler>, std::tuple<_Tps ...> >::value)), ThreadHandler>::_MoveConstructibleTuple<_UElements ...>() && std::_TC<((1 == sizeof... (_UElements)) && (! std::is_same<std::tuple<ThreadHandler>, std::tuple<_Tps ...> >::value)), ThreadHandler>::_ImplicitlyMoveConvertibleTuple<_UElements ...>()) && std::_TC<(std::is_same<_Dummy, void>::value && (1 == 1)), ThreadHandler>::_NonNestedTuple<tuple<_Tps ...>&&>()), bool>::type <anonymous> > constexpr std::tuple<_Elements>::tuple(std::tuple<_Args1 ...>&&)’
         constexpr tuple(tuple<_UElements...>&& __in)
                   ^~~~~
/usr/local/include/c++/8.1.0/tuple:702:19: note:   template argument deduction/substitution failed:
In file included from main.cpp:1:
/usr/local/include/c++/8.1.0/thread:258:4: note:   ‘ThreadHandler’ is not derived from ‘std::tuple<_Tps ...>’
  } };
    ^
In file included from /usr/local/include/c++/8.1.0/bits/unique_ptr.h:37,
                 from /usr/local/include/c++/8.1.0/memory:80,
                 from /usr/local/include/c++/8.1.0/thread:39,
                 from main.cpp:1:
/usr/local/include/c++/8.1.0/tuple:690:28: note: candidate: ‘template<class ... _UElements, class _Dummy, typename std::enable_if<((std::_TC<((1 == sizeof... (_UElements)) && (! std::is_same<std::tuple<ThreadHandler>, std::tuple<_Tps ...> >::value)), ThreadHandler>::_ConstructibleTuple<_UElements ...>() && (! std::_TC<((1 == sizeof... (_UElements)) && (! std::is_same<std::tuple<ThreadHandler>, std::tuple<_Tps ...> >::value)), ThreadHandler>::_ImplicitlyConvertibleTuple<_UElements ...>())) && std::_TC<(std::is_same<_Dummy, void>::value && (1 == 1)), ThreadHandler>::_NonNestedTuple<const tuple<_Tps ...>&>()), bool>::type <anonymous> > constexpr std::tuple<_Elements>::tuple(const std::tuple<_Args1 ...>&)’
         explicit constexpr tuple(const tuple<_UElements...>& __in)
                            ^~~~~
/usr/local/include/c++/8.1.0/tuple:690:28: note:   template argument deduction/substitution failed:
In file included from main.cpp:1:
/usr/local/include/c++/8.1.0/thread:258:4: note:   ‘ThreadHandler’ is not derived from ‘const std::tuple<_Tps ...>’
  } };
    ^
In file included from /usr/local/include/c++/8.1.0/bits/unique_ptr.h:37,
                 from /usr/local/include/c++/8.1.0/memory:80,
                 from /usr/local/include/c++/8.1.0/thread:39,
                 from main.cpp:1:
/usr/local/include/c++/8.1.0/tuple:678:19: note: candidate: ‘template<class ... _UElements, class _Dummy, typename std::enable_if<((std::_TC<((1 == sizeof... (_UElements)) && (! std::is_same<std::tuple<ThreadHandler>, std::tuple<_Tps ...> >::value)), ThreadHandler>::_ConstructibleTuple<_UElements ...>() && std::_TC<((1 == sizeof... (_UElements)) && (! std::is_same<std::tuple<ThreadHandler>, std::tuple<_Tps ...> >::value)), ThreadHandler>::_ImplicitlyConvertibleTuple<_UElements ...>()) && std::_TC<(std::is_same<_Dummy, void>::value && (1 == 1)), ThreadHandler>::_NonNestedTuple<const tuple<_Tps ...>&>()), bool>::type <anonymous> > constexpr std::tuple<_Elements>::tuple(const std::tuple<_Args1 ...>&)’
         constexpr tuple(const tuple<_UElements...>& __in)
                   ^~~~~
/usr/local/include/c++/8.1.0/tuple:678:19: note:   template argument deduction/substitution failed:
In file included from main.cpp:1:
/usr/local/include/c++/8.1.0/thread:258:4: note:   ‘ThreadHandler’ is not derived from ‘const std::tuple<_Tps ...>’
  } };
    ^
In file included from /usr/local/include/c++/8.1.0/bits/unique_ptr.h:37,
                 from /usr/local/include/c++/8.1.0/memory:80,
                 from /usr/local/include/c++/8.1.0/thread:39,
                 from main.cpp:1:
/usr/local/include/c++/8.1.0/tuple:662:17: note: candidate: ‘constexpr std::tuple<_Elements>::tuple(std::tuple<_Elements>&&) [with _Elements = {ThreadHandler}]’
       constexpr tuple(tuple&&) = default;
                 ^~~~~
/usr/local/include/c++/8.1.0/tuple:662:17: note:   no known conversion for argument 1 from ‘ThreadHandler’ to ‘std::tuple<ThreadHandler>&&’
/usr/local/include/c++/8.1.0/tuple:657:28: note: candidate: ‘template<class ... _UElements, typename std::enable_if<((std::_TC<((1 == sizeof... (_UElements)) && std::_TC<(sizeof... (_UElements) == 1), ThreadHandler>::_NotSameTuple<_UElements ...>()), ThreadHandler>::_MoveConstructibleTuple<_UElements ...>() && (! std::_TC<((1 == sizeof... (_UElements)) && std::_TC<(sizeof... (_UElements) == 1), ThreadHandler>::_NotSameTuple<_UElements ...>()), ThreadHandler>::_ImplicitlyMoveConvertibleTuple<_UElements ...>())) && (1 >= 1)), bool>::type <anonymous> > constexpr std::tuple<_Elements>::tuple(_UElements&& ...)’
         explicit constexpr tuple(_UElements&&... __elements)
                            ^~~~~
/usr/local/include/c++/8.1.0/tuple:657:28: note:   template argument deduction/substitution failed:
/usr/local/include/c++/8.1.0/tuple:656:21: error: no type named ‘type’ in ‘struct std::enable_if<false, bool>’
         bool>::type=false>
                     ^~~~~
/usr/local/include/c++/8.1.0/tuple:646:19: note: candidate: ‘template<class ... _UElements, typename std::enable_if<((std::_TC<((1 == sizeof... (_UElements)) && std::_TC<(sizeof... (_UElements) == 1), ThreadHandler>::_NotSameTuple<_UElements ...>()), ThreadHandler>::_MoveConstructibleTuple<_UElements ...>() && std::_TC<((1 == sizeof... (_UElements)) && std::_TC<(sizeof... (_UElements) == 1), ThreadHandler>::_NotSameTuple<_UElements ...>()), ThreadHandler>::_ImplicitlyMoveConvertibleTuple<_UElements ...>()) && (1 >= 1)), bool>::type <anonymous> > constexpr std::tuple<_Elements>::tuple(_UElements&& ...)’
         constexpr tuple(_UElements&&... __elements)
                   ^~~~~
/usr/local/include/c++/8.1.0/tuple:646:19: note:   template argument deduction/substitution failed:
/usr/local/include/c++/8.1.0/tuple:645:21: error: no type named ‘type’ in ‘struct std::enable_if<false, bool>’
         bool>::type=true>
                     ^~~~
/usr/local/include/c++/8.1.0/tuple:619:26: note: candidate: ‘template<class _Dummy, typename std::enable_if<((std::_TC<std::is_same<_Dummy, void>::value, ThreadHandler>::_ConstructibleTuple<ThreadHandler>() && (! std::_TC<std::is_same<_Dummy, void>::value, ThreadHandler>::_ImplicitlyConvertibleTuple<ThreadHandler>())) && (1 >= 1)), bool>::type <anonymous> > constexpr std::tuple<_Elements>::tuple(const _Elements& ...)’
       explicit constexpr tuple(const _Elements&... __elements)
                          ^~~~~
/usr/local/include/c++/8.1.0/tuple:619:26: note:   template argument deduction/substitution failed:
/usr/local/include/c++/8.1.0/tuple:618:28: error: no type named ‘type’ in ‘struct std::enable_if<false, bool>’
                bool>::type=false>
                            ^~~~~
/usr/local/include/c++/8.1.0/tuple:608:19: note: candidate: ‘template<class _Dummy, typename std::enable_if<((std::_TC<std::is_same<_Dummy, void>::value, ThreadHandler>::_ConstructibleTuple<ThreadHandler>() && std::_TC<std::is_same<_Dummy, void>::value, ThreadHandler>::_ImplicitlyConvertibleTuple<ThreadHandler>()) && (1 >= 1)), bool>::type <anonymous> > constexpr std::tuple<_Elements>::tuple(const _Elements& ...)’
         constexpr tuple(const _Elements&... __elements)
                   ^~~~~
/usr/local/include/c++/8.1.0/tuple:608:19: note:   template argument deduction/substitution failed:
/usr/local/include/c++/8.1.0/tuple:607:28: error: no type named ‘type’ in ‘struct std::enable_if<false, bool>’
                bool>::type=true>
                            ^~~~
/usr/local/include/c++/8.1.0/tuple:591:26: note: candidate: ‘template<class _Dummy, typename std::enable_if<(std::tuple<ThreadHandler>::_TC2<_Dummy>::_DefaultConstructibleTuple() && (! std::tuple<ThreadHandler>::_TC2<_Dummy>::_ImplicitlyDefaultConstructibleTuple())), bool>::type <anonymous> > constexpr std::tuple<_Elements>::tuple()’
       explicit constexpr tuple()
                          ^~~~~
/usr/local/include/c++/8.1.0/tuple:591:26: note:   template argument deduction/substitution failed:
In file included from main.cpp:1:
/usr/local/include/c++/8.1.0/thread:258:4: note:   candidate expects 0 arguments, 1 provided
  } };
    ^
In file included from /usr/local/include/c++/8.1.0/bits/unique_ptr.h:37,
                 from /usr/local/include/c++/8.1.0/memory:80,
                 from /usr/local/include/c++/8.1.0/thread:39,
                 from main.cpp:1:
/usr/local/include/c++/8.1.0/tuple:581:17: note: candidate: ‘template<class _Dummy, typename std::enable_if<std::tuple<ThreadHandler>::_TC2<_Dummy>::_ImplicitlyDefaultConstructibleTuple(), bool>::type <anonymous> > constexpr std::tuple<_Elements>::tuple()’
       constexpr tuple()
                 ^~~~~
/usr/local/include/c++/8.1.0/tuple:581:17: note:   template argument deduction/substitution failed:
In file included from main.cpp:1:
/usr/local/include/c++/8.1.0/thread:258:4: note:   candidate expects 0 arguments, 1 provided
  } };
    ^
/usr/local/include/c++/8.1.0/thread:258:4: error: could not convert ‘{<expression error>}’ from ‘<brace-enclosed initializer list>’ to ‘std::thread::_Invoker<std::tuple<ThreadHandler> >’
In file included from /usr/local/include/c++/8.1.0/bits/unique_ptr.h:37,
                 from /usr/local/include/c++/8.1.0/memory:80,
                 from /usr/local/include/c++/8.1.0/thread:39,
                 from main.cpp:1:
/usr/local/include/c++/8.1.0/tuple: In instantiation of ‘constexpr std::_Head_base<_Idx, _Head, false>::_Head_base(_UHead&&) [with _UHead = ThreadHandler; long unsigned int _Idx = 0; _Head = ThreadHandler]’:
/usr/local/include/c++/8.1.0/tuple:373:49:   required from ‘constexpr std::_Tuple_impl<_Idx, _Head>::_Tuple_impl(std::_Tuple_impl<_Idx, _Head>&&) [with long unsigned int _Idx = 0; _Head = ThreadHandler]’
/usr/local/include/c++/8.1.0/tuple:662:17:   required from ‘std::thread::_State_impl<_Callable>::_State_impl(_Callable&&) [with _Callable = std::thread::_Invoker<std::tuple<ThreadHandler> >]’
/usr/local/include/c++/8.1.0/thread:197:20:   required from ‘static std::thread::_State_ptr std::thread::_S_make_state(_Callable&&) [with _Callable = std::thread::_Invoker<std::tuple<ThreadHandler> >; std::thread::_State_ptr = std::unique_ptr<std::thread::_State>]’
/usr/local/include/c++/8.1.0/thread:126:38:   required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = ThreadHandler&; _Args = {}]’
main.cpp:14:23:   required from here
/usr/local/include/c++/8.1.0/tuple:133:42: error: use of deleted function ‘ThreadHandler::ThreadHandler(ThreadHandler&&)’
  : _M_head_impl(std::forward<_UHead>(__h)) { }
                                          ^
main.cpp:4:8: note: ‘ThreadHandler::ThreadHandler(ThreadHandler&&)’ is implicitly deleted because the default definition would be ill-formed:
 struct ThreadHandler
        ^~~~~~~~~~~~~
main.cpp:4:8: error: use of deleted function ‘std::condition_variable::condition_variable(const std::condition_variable&)’
In file included from main.cpp:2:
/usr/local/include/c++/8.1.0/condition_variable:82:5: note: declared here
     condition_variable(const condition_variable&) = delete;
     ^~~~~~~~~~~~~~~~~~
In file included from main.cpp:1:
/usr/local/include/c++/8.1.0/thread: In instantiation of ‘std::thread::_State_impl<_Callable>::_State_impl(_Callable&&) [with _Callable = std::thread::_Invoker<std::tuple<ThreadHandler> >]’:
/usr/local/include/c++/8.1.0/thread:197:20:   required from ‘static std::thread::_State_ptr std::thread::_S_make_state(_Callable&&) [with _Callable = std::thread::_Invoker<std::tuple<ThreadHandler> >; std::thread::_State_ptr = std::unique_ptr<std::thread::_State>]’
/usr/local/include/c++/8.1.0/thread:126:38:   required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = ThreadHandler&; _Args = {}]’
main.cpp:14:23:   required from here
/usr/local/include/c++/8.1.0/thread:221:14: note: synthesized method ‘constexpr std::tuple<_Elements>::tuple(std::tuple<_Elements>&&) [with _Elements = {ThreadHandler}]’ first required here
       struct _Invoker
              ^~~~~~~~
/usr/local/include/c++/8.1.0/thread:182:69: note: synthesized method ‘constexpr std::thread::_Invoker<std::tuple<ThreadHandler> >::_Invoker(std::thread::_Invoker<std::tuple<ThreadHandler> >&&)’ first required here
  _State_impl(_Callable&& __f) : _M_func(std::forward<_Callable>(__f))
like image 919
Masked Man Avatar asked Jun 28 '18 16:06

Masked Man


2 Answers

You pass instance of ThreadHandler by value to std::thread but as stated in documentation for std::condition_variable

The class std::condition_variable is a StandardLayoutType. It is not CopyConstructible, MoveConstructible, CopyAssignable, MoveAssignable.

Emphasis is mine. So it makes struct ThreadHandler not copyable/movable either. Possible solution is to pass it by reference:

std::thread t1(std::ref(th1));

live example

Note: you do not have to make ThreadHandler to be a functor, just general method would work:

struct ThreadHandler {
    void thread_func() { }

    std::condition_variable cond; 
};

int main() {
    ThreadHandler th1;
    std::thread t1(&ThreadHandler::thread_func, &th1);
    t1.join(); 
}

this not only would solve your issue (I passed address of th1 so no copy involved) but make it more readable (method name is explicit) and flexible (you can use different methods for different threads)

like image 176
Slava Avatar answered Nov 05 '22 20:11

Slava


You can never just copy synchronization objects. Is it locked? Unlocked? In the middle of locking or unlocking?

C++ condition_variables don't have copy constructors and it doesn't make sense for them to have them. It is a shame the error messages aren't more useful though.

like image 24
Zan Lynx Avatar answered Nov 05 '22 20:11

Zan Lynx