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))
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)
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With