Using Boost, I am trying to emplace() a key/value pair into a boost::container::map. The value needs multiple arguments for the constructor. From what I've been able to find, I need to use piecewise_construct and pass the constructor args in tuples. This works with std::map<K,V>, but I can't get it to work using boost::container::map<K,V> The closest Boost doc I can find shows boost::unordered_multimap<K,V>, but not a plain map<K,V>.
#include <map>
#include <boost/tuple/tuple.hpp>
#include <boost/container/map.hpp>
#include <boost/unordered_set.hpp>
class A {
public:
/**/ A( int ) { }
bool operator<( const A & ) const { return false; }
} ;
class B {
public:
/**/ B( int, const char * ) { }
} ;
int
main( int, char ** )
{
A a( 100 );
B b( 200, "foo" );
std::map<A,B> mgood;
mgood.emplace( std::piecewise_construct,
std::make_tuple( 100 ),
std::make_tuple( 200, "Hello" ) );
#if 1
boost::container::map<A,B> mbad;
mbad.emplace( boost::unordered::piecewise_construct,
boost::make_tuple( 300 ),
boost::make_tuple( 400, "World" ) );
#endif
}
The g++-4.9.2 error messages are impenetrable (to me, anyway):
make -k tst g++ -DBOOST_LOG_DYN_LINK -g -std=c++11 -c -o tst.o
tst.cc In file included from
/usr/local/include/boost/container/detail/tree.hpp:25:0,
from /usr/local/include/boost/container/map.hpp:30,
from tst.cc:59: /usr/local/include/boost/container/allocator_traits.hpp: In
instantiation of âstatic void
boost::container::allocator_traits::priv_construct(boost::move_detail::false_type,
Allocator&, T*, Args&& ...) [with T =
boost::container::container_detail::pair; Args = {const
boost::unordered::piecewise_construct_t&, boost::tuples::tuple, boost::tuples::tuple}; Allocator =
boost::container::new_allocator, void*, (boost::container::tree_type_enum)0u, true> >;
boost::move_detail::false_type =
boost::move_detail::integral_constant]â:
/usr/local/include/boost/container/allocator_traits.hpp:353:86:
required from âstatic void
boost::container::allocator_traits::construct(Allocator&,
T*, Args&& ...) [with T = boost::container::container_detail::pair; Args = {const boost::unordered::piecewise_construct_t&,
boost::tuples::tuple,
boost::tuples::tuple}; Allocator =
boost::container::new_allocator, void*, (boost::container::tree_type_enum)0u, true> >]â
/usr/local/include/boost/container/detail/node_alloc_holder.hpp:167:81:
required from
âboost::container::container_detail::node_alloc_holder::NodePtr
boost::container::container_detail::node_alloc_holder::create_node(Args&& ...) [with Args = {const
boost::unordered::piecewise_construct_t&, boost::tuples::tuple, boost::tuples::tuple}; Allocator =
boost::container::new_allocator >; ICont =
boost::intrusive::rbtree_impl, void*, (boost::container::tree_type_enum)0u, true>,
boost::intrusive::rbtree_node_traits,
(boost::intrusive::link_mode_type)0u, boost::intrusive::dft_tag, 3u>,
void,
boost::container::value_to_node_compare, void*, (boost::container::tree_type_enum)0u, true>,
boost::intrusive::tree_value_compare,
std::less,
boost::container::container_detail::select1st >
, long unsigned int, true, void>; boost::container::container_detail::node_alloc_holder::NodePtr =
boost::container::container_detail::tree_node,
void*, (boost::container::tree_type_enum)0u, true>]â
/usr/local/include/boost/container/detail/tree.hpp:922:94: required
from
âstd::pair,
Options:: tree_type, Options:: optimize_size>::type::iterator, false>,
bool> boost::container::container_detail::tree::emplace_unique(Args&& ...) [with Args =
{const boost::unordered::piecewise_construct_t&,
boost::tuples::tuple,
boost::tuples::tuple}; Key = A; T = std::pair;
KeyOfValue =
boost::container::container_detail::select1st >;
Compare = std::less; Allocator =
boost::container::new_allocator >; Options =
boost::container::tree_opt<(boost::container::tree_type_enum)0u,
true>; typename
boost::container::container_detail::intrusive_tree_type,
Options:: tree_type, Options:: optimize_size>::type::iterator =
boost::intrusive::tree_iterator, void*, (boost::container::tree_type_enum)0u, true>,
boost::intrusive::rbtree_node_traits,
(boost::intrusive::link_mode_type)0u, boost::intrusive::dft_tag, 3u>,
false>]â /usr/local/include/boost/container/map.hpp:665:72:
required from âstd::pair, boost::container::container_detail::select1st >, Compare, Allocator, MapOptions>::iterator, bool> boost::container::map::emplace(Args&& ...) [with Args = {const
boost::unordered::piecewise_construct_t&, boost::tuples::tuple, boost::tuples::tuple}; Key = A; T = B;
Compare = std::less; Allocator =
boost::container::new_allocator >; MapOptions =
boost::container::tree_opt<(boost::container::tree_type_enum)0u,
true>; typename boost::container::container_detail::tree,
boost::container::container_detail::select1st >, Compare, Allocator, MapOptions>::iterator = boost::container::container_detail::iterator_from_iiterator, void*, (boost::container::tree_type_enum)0u, true>,
boost::intrusive::rbtree_node_traits,
(boost::intrusive::link_mode_type)0u, boost::intrusive::dft_tag, 3u>,
false>, false>]â tst.cc:90:53: required from here
/usr/local/include/boost/container/allocator_traits.hpp:408:10: error:
no matching function for call to
âboost::container::container_detail::pair::pair(const
boost::unordered::piecewise_construct_t&, boost::tuples::tuple, boost::tuples::tuple)â
{ ::new((void)p, boost_container_new_t()) T(::boost::forward(args)...); }
^ /usr/local/include/boost/container/allocator_traits.hpp:408:10: note:
candidates are: In file included from
/usr/local/include/boost/container/detail/tree.hpp:36:0,
from /usr/local/include/boost/container/map.hpp:30,
from tst.cc:59: /usr/local/include/boost/container/detail/pair.hpp:146:4: note:
template
boost::container::container_detail::pair::pair(std::pair<_U1,
_U2>&&)
pair(BOOST_RV_REF_BEG std::pair BOOST_RV_REF_END p)
^ /usr/local/include/boost/container/detail/pair.hpp:146:4: note: template argument deduction/substitution failed: In file included from
/usr/local/include/boost/container/detail/tree.hpp:25:0,
from /usr/local/include/boost/container/map.hpp:30,
from tst.cc:59: /usr/local/include/boost/container/allocator_traits.hpp:408:10: note:
types âstd::pair<_T1, _T2>â and âconst
boost::unordered::piecewise_construct_tâ have incompatible
cv-qualifiers
{ ::new((void*)p, boost_container_new_t()) T(::boost::forward(args)...); }
^ In file included from /usr/local/include/boost/container/detail/tree.hpp:36:0,
from /usr/local/include/boost/container/map.hpp:30,
from tst.cc:59: /usr/local/include/boost/container/detail/pair.hpp:141:4: note:
boost::container::container_detail::pair::pair(std::pair<_T1,
_T2>&&) [with T1 = A; T2 = B]
pair(BOOST_RV_REF_BEG std::pair BOOST_RV_REF_END p)
^ /usr/local/include/boost/container/detail/pair.hpp:141:4: note: candidate expects 1 argument, 3 provided
/usr/local/include/boost/container/detail/pair.hpp:137:4: note:
template
boost::container::container_detail::pair::pair(const
std::pair<_U1, _U2>&)
pair(const std::pair& p)
^ /usr/local/include/boost/container/detail/pair.hpp:137:4: note: template argument deduction/substitution failed: In file included from
/usr/local/include/boost/container/detail/tree.hpp:25:0,
from /usr/local/include/boost/container/map.hpp:30,
from tst.cc:59: /usr/local/include/boost/container/allocator_traits.hpp:408:10: note:
âconst boost::unordered::piecewise_construct_tâ is not derived
from âconst std::pair<_T1, _T2>â
{ ::new((void*)p, boost_container_new_t()) T(::boost::forward(args)...); }
^ In file included from /usr/local/include/boost/container/detail/tree.hpp:36:0,
from /usr/local/include/boost/container/map.hpp:30,
from tst.cc:59: /usr/local/include/boost/container/detail/pair.hpp:132:4: note:
boost::container::container_detail::pair::pair(const
std::pair<_T1, _T2>&) [with T1 = A; T2 = B]
pair(const std::pair& x)
^ /usr/local/include/boost/container/detail/pair.hpp:132:4: note: candidate expects 1 argument, 3 provided
/usr/local/include/boost/container/detail/pair.hpp:126:4: note:
template
boost::container::container_detail::pair::pair(U&&, V&&)
pair(BOOST_FWD_REF(U) u, BOOST_FWD_REF(V) v)
^ /usr/local/include/boost/container/detail/pair.hpp:126:4: note: template argument deduction/substitution failed: In file included from
/usr/local/include/boost/container/detail/tree.hpp:25:0,
from /usr/local/include/boost/container/map.hpp:30,
from tst.cc:59: /usr/local/include/boost/container/allocator_traits.hpp:408:10: note:
candidate expects 2 arguments, 3 provided
{ ::new((void*)p, boost_container_new_t()) T(::boost::forward(args)...); }
^ In file included from /usr/local/include/boost/container/detail/tree.hpp:36:0,
from /usr/local/include/boost/container/map.hpp:30,
from tst.cc:59: /usr/local/include/boost/container/detail/pair.hpp:120:4: note:
boost::container::container_detail::pair::pair(const T1&,
const T2&) [with T1 = A; T2 = B]
pair(const T1 &t1, const T2 &t2)
^ /usr/local/include/boost/container/detail/pair.hpp:120:4: note: candidate expects 2 arguments, 3 provided
/usr/local/include/boost/container/detail/pair.hpp:115:4: note:
template
boost::container::container_detail::pair::pair(boost::container::container_detail::pair&&)
pair(BOOST_RV_REF_BEG pair BOOST_RV_REF_END p)
^ /usr/local/include/boost/container/detail/pair.hpp:115:4: note: template argument deduction/substitution failed: In file included from
/usr/local/include/boost/container/detail/tree.hpp:25:0,
from /usr/local/include/boost/container/map.hpp:30,
from tst.cc:59: /usr/local/include/boost/container/allocator_traits.hpp:408:10: note:
types âboost::container::container_detail::pairâ and
âconst boost::unordered::piecewise_construct_tâ have incompatible
cv-qualifiers
{ ::new((void*)p, boost_container_new_t()) T(::boost::forward(args)...); }
^ In file included from /usr/local/include/boost/container/detail/tree.hpp:36:0,
from /usr/local/include/boost/container/map.hpp:30,
from tst.cc:59: /usr/local/include/boost/container/detail/pair.hpp:110:4: note:
template
boost::container::container_detail::pair::pair(const
boost::container::container_detail::pair&)
pair(const pair &p)
^ /usr/local/include/boost/container/detail/pair.hpp:110:4: note: template argument deduction/substitution failed: In file included from
/usr/local/include/boost/container/detail/tree.hpp:25:0,
from /usr/local/include/boost/container/map.hpp:30,
from tst.cc:59: /usr/local/include/boost/container/allocator_traits.hpp:408:10: note:
âconst boost::unordered::piecewise_construct_tâ is not derived
from âconst boost::container::container_detail::pairâ
{ ::new((void*)p, boost_container_new_t()) T(::boost::forward(args)...); }
^ In file included from /usr/local/include/boost/container/detail/tree.hpp:36:0,
from /usr/local/include/boost/container/map.hpp:30,
from tst.cc:59: /usr/local/include/boost/container/detail/pair.hpp:105:4: note:
boost::container::container_detail::pair::pair(boost::container::container_detail::pair&&) [with T1
= A; T2 = B]
pair(BOOST_RV_REF(pair) p)
^ /usr/local/include/boost/container/detail/pair.hpp:105:4: note: candidate expects 1 argument, 3 provided
/usr/local/include/boost/container/detail/pair.hpp:100:4: note:
boost::container::container_detail::pair::pair(const
boost::container::container_detail::pair&) [with T1 = A; T2 =
B]
pair(const pair& x)
^ /usr/local/include/boost/container/detail/pair.hpp:100:4: note: candidate expects 1 argument, 3 provided
/usr/local/include/boost/container/detail/pair.hpp:95:4: note:
boost::container::container_detail::pair::pair() [with T1 = A;
T2 = B]
pair()
^ /usr/local/include/boost/container/detail/pair.hpp:95:4: note: candidate expects 0 arguments, 3 provided : recipe for target
'tst.o' failed make: *** [tst.o] Error 1 make: Target 'tst' not remade
because of errors.
Compilation exited abnormally with code 2 at Sat Apr 2 17:11:28
Can you point me in a useful direction? (I'd prefer not to mix boost and std containers; it should be possible to emplace into a boost::container::map, right?)
It appears that piecewise_construct is not implemented for boost::pair (which is the type for boost::container::map entries). See .../boost/container/detail/pair.hpp:151:
//piecewise_construct missing
//template <class U, class V> pair(pair<U, V>&& p);
//template <class... Args1, class... Args2>
// pair(piecewise_construct_t, tuple<Args1...> first_args,
// tuple<Args2...> second_args);
I guess the implementation for this is tough.
piecewise_construct support for both C++03 and C++11 capable compilers was added in commit:
https://github.com/boostorg/container/commit/79a75f470e75f35f5f2a91e10fcc67d03b0a2160
and will be officially released in Boost 1.62. The following code compiles fine:
#include <boost/tuple/tuple.hpp>
#include <tuple>
#include <boost/container/map.hpp>
class A {
public:
/**/ A( int ) { }
bool operator<( const A & ) const { return false; }
} ;
class B {
public:
/**/ B( int, const char * ) { }
} ;
int main( int, char *[] )
{
A a( 100 );
B b( 200, "foo" );
boost::container::map<A,B> m;
//1) Both Boost.Tuple and std tuple supported
//2) std:: or boost::container::piecewise_construct supported
m.emplace( boost::container::piecewise_construct,
boost::make_tuple( 300 ),
boost::make_tuple( 400, "World" ) );
m.emplace( std::piecewise_construct,
std::make_tuple( 400 ),
std::make_tuple( 500, "World2" ) );
}
Related
Here's a watered down example of the code I'm try to compile:
#include <iostream>
#include <functional>
template <class F>
auto foo(F&& fun)
{
return [callback = std::forward<F>(fun)](auto&&... args) {
std::invoke(callback, std::forward<decltype(args)>(args)...);
};
}
int main()
{
std::string cur("running"), target("ok");
foo([s1 = cur, s2 = target](std::string const& arg) /*mutable*/ {
if (s1 == arg)
{
std::cout << s1 << std::endl;
}
})("not ok");
return 0;
}
put simply I have a function foo that accepts callables, and is supposed to build a new callable from them. For the sake of the example, above I'm just invoking the fun argument but in the real case there are some decorations done to the callable and the result is placed into a data structure that invokes such "actions" under some conditions.
This example compiles and works just fine. The problem manifests when trying to pass mutable lambdas to foo. When I uncomment the mutable keyword above, I get this compilation error:
main.cpp: In instantiation of 'foo<main()::<lambda(const string&)> >(main()::<lambda(const string&)>&&)::<lambda(auto:1&& ...)> [with auto:1 = {const char (&)[7]}]':
main.cpp:21:7: required from here
main.cpp:8:20: error: no matching function for call to 'invoke(const main()::<lambda(const string&)>&, const char [7])'
8 | std::invoke(callback, std::forward<decltype(args)>(args)...);
| ~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from main.cpp:2:
/usr/local/include/c++/11.2.0/functional:94:5: note: candidate: 'template<class _Callable, class ... _Args> std::invoke_result_t<_Callable, _Args ...> std::invoke(_Callable&&, _Args&& ...)'
94 | invoke(_Callable&& __fn, _Args&&... __args)
| ^~~~~~
/usr/local/include/c++/11.2.0/functional:94:5: note: template argument deduction/substitution failed:
In file included from /usr/local/include/c++/11.2.0/bits/move.h:57,
from /usr/local/include/c++/11.2.0/bits/nested_exception.h:40,
from /usr/local/include/c++/11.2.0/exception:148,
from /usr/local/include/c++/11.2.0/ios:39,
from /usr/local/include/c++/11.2.0/ostream:38,
from /usr/local/include/c++/11.2.0/iostream:39,
from main.cpp:1:
/usr/local/include/c++/11.2.0/type_traits: In substitution of 'template<class _Fn, class ... _Args> using invoke_result_t = typename std::invoke_result::type [with _Fn = const main()::<lambda(const string&)>&; _Args = {const char (&)[7]}]':
/usr/local/include/c++/11.2.0/functional:94:5: required by substitution of 'template<class _Callable, class ... _Args> std::invoke_result_t<_Callable, _Args ...> std::invoke(_Callable&&, _Args&& ...) [with _Callable = const main()::<lambda(const string&)>&; _Args = {const char (&)[7]}]'
main.cpp:8:20: required from 'foo<main()::<lambda(const string&)> >(main()::<lambda(const string&)>&&)::<lambda(auto:1&& ...)> [with auto:1 = {const char (&)[7]}]'
main.cpp:21:7: required from here
/usr/local/include/c++/11.2.0/type_traits:2933:11: error: no type named 'type' in 'struct std::invoke_result<const main()::<lambda(const string&)>&, const char (&)[7]>'
2933 | using invoke_result_t = typename invoke_result<_Fn, _Args...>::type;
| ^~~~~~~~~~~~~~~
Any idea why is that? Can my foo accept mutable lambdas as well?
Just add mutable to the lambda inside the foo:
template <class F>
auto foo(F&& fun)
{
return [callback = std::forward<F>(fun)](auto&&... args) mutable {
//^^^
std::invoke(callback, std::forward<decltype(args)>(args)...);
};
}
I'm facing a thread problem.
I tried to execute function inside a thread from Chronometer class including a while loop:
Here is the part code:
for(int i = 0; i<car_data.size();i++)
{
if(car_data[i]->checkArea(frame, pt1_zone, pt2_zone))
{
std::thread(&Chronometer::start_chrono, car_crono[i], std::ref(chrono));
cv::rectangle(frame, car_data[i]->pt1, car_data[i]->pt2, cv::Scalar(255,0,0), 1, cv::LINE_8,0);
//cv::putText(frame, "Parked", car_data[i]->pt1, cv::FONT_HERSHEY_DUPLEX, 0.9, cv::Scalar( 50, 255, 50 ));
//occupancy_state = place.occupancyTrue();
//place_1.occupancy = true;
The type of car_crono and chrono
std::vector<Chronometer*> car_crono;
Chronometer chrono;
Here is my class Chronometer:
class Chronometer
{
private:
static int hour, min, sec;
//std::stringstream ss;
//Chronometer chrono;
public:
Chronometer();
static Chronometer& start_chrono(Chronometer& chrono);
static Chronometer& finish_chrono(Chronometer& chrono);
friend std::ostream& operator<<(std::ostream& flux, Chronometer t);
Chronometer& operator=(const Chronometer& other);
~Chronometer();
};
For the thread I tried several kind of parameters. The last one:
std::thread(&Chronometer::start_chrono, car_crono[i], std::ref(chrono));
I guessed a ref was necessary but doesn't change.
Here is the full error
/usr/include/c++/7/thread: In instantiation of ‘struct std::thread::_Invoker<std::tuple<Chronometer& (*)(Chronometer&), Chronometer*, std::reference_wrapper<Chronometer> > >’:
/usr/include/c++/7/thread:127:22: required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = Chronometer& (*)(Chronometer&); _Args = {Chronometer*&, std::reference_wrapper<Chronometer>}]’
recognizer_rtsp.cxx:348:76: required from here
/usr/include/c++/7/thread:240:2: error: no matching function for call to ‘std::thread::_Invoker<std::tuple<Chronometer& (*)(Chronometer&), Chronometer*, std::reference_wrapper<Chronometer> > >::_M_invoke(std::thread::_Invoker<std::tuple<Chronometer& (*)(Chronometer&), Chronometer*, std::reference_wrapper<Chronometer> > >::_Indices)’
operator()()
^~~~~~~~
/usr/include/c++/7/thread:231:4: note: candidate: template<long unsigned int ..._Ind> decltype (std::__invoke((_S_declval<_Ind>)()...)) std::thread::_Invoker<_Tuple>::_M_invoke(std::_Index_tuple<_Ind ...>) [with long unsigned int ..._Ind = {_Ind ...}; _Tuple = std::tuple<Chronometer& (*)(Chronometer&), Chronometer*, std::reference_wrapper<Chronometer> >]
_M_invoke(_Index_tuple<_Ind...>)
^~~~~~~~~
/usr/include/c++/7/thread:231:4: note: template argument deduction/substitution failed:
/usr/include/c++/7/thread: In substitution of ‘template<long unsigned int ..._Ind> decltype (std::__invoke(_S_declval<_Ind>()...)) std::thread::_Invoker<std::tuple<Chronometer& (*)(Chronometer&), Chronometer*, std::reference_wrapper<Chronometer> > >::_M_invoke<_Ind ...>(std::_Index_tuple<_Ind1 ...>) [with long unsigned int ..._Ind = {0, 1, 2}]’:
/usr/include/c++/7/thread:240:2: required from ‘struct std::thread::_Invoker<std::tuple<Chronometer& (*)(Chronometer&), Chronometer*, std::reference_wrapper<Chronometer> > >’
/usr/include/c++/7/thread:127:22: required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = Chronometer& (*)(Chronometer&); _Args = {Chronometer*&, std::reference_wrapper<Chronometer>}]’
recognizer_rtsp.cxx:348:76: required from here
/usr/include/c++/7/thread:233:29: error: no matching function for call to ‘__invoke(std::__tuple_element_t<0, std::tuple<Chronometer& (*)(Chronometer&), Chronometer*, std::reference_wrapper<Chronometer> > >, std::__tuple_element_t<1, std::tuple<Chronometer& (*)(Chronometer&), Chronometer*, std::reference_wrapper<Chronometer> > >, std::__tuple_element_t<2, std::tuple<Chronometer& (*)(Chronometer&), Chronometer*, std::reference_wrapper<Chronometer> > >)’
-> decltype(std::__invoke(_S_declval<_Ind>()...))
~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/7/tuple:41:0,
from /usr/include/c++/7/bits/stl_map.h:63,
from /usr/include/c++/7/map:61,
from ../alpr_utils.h:7,
from recognizer_rtsp.cxx:34:
/usr/include/c++/7/bits/invoke.h:89:5: note: candidate: template<class _Callable, class ... _Args> constexpr typename std::__invoke_result<_Functor, _ArgTypes>::type std::__invoke(_Callable&&, _Args&& ...)
__invoke(_Callable&& __fn, _Args&&... __args)
^~~~~~~~
/usr/include/c++/7/bits/invoke.h:89:5: note: template argument deduction/substitution failed:
/usr/include/c++/7/bits/invoke.h: In substitution of ‘template<class _Callable, class ... _Args> constexpr typename std::__invoke_result<_Functor, _ArgTypes>::type std::__invoke(_Callable&&, _Args&& ...) [with _Callable = Chronometer& (*)(Chronometer&); _Args = {Chronometer*, std::reference_wrapper<Chronometer>}]’:
/usr/include/c++/7/thread:233:29: required by substitution of ‘template<long unsigned int ..._Ind> decltype (std::__invoke(_S_declval<_Ind>()...)) std::thread::_Invoker<std::tuple<Chronometer& (*)(Chronometer&), Chronometer*, std::reference_wrapper<Chronometer> > >::_M_invoke<_Ind ...>(std::_Index_tuple<_Ind1 ...>) [with long unsigned int ..._Ind = {0, 1, 2}]’
/usr/include/c++/7/thread:240:2: required from ‘struct std::thread::_Invoker<std::tuple<Chronometer& (*)(Chronometer&), Chronometer*, std::reference_wrapper<Chronometer> > >’
/usr/include/c++/7/thread:127:22: required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = Chronometer& (*)(Chronometer&); _Args = {Chronometer*&, std::reference_wrapper<Chronometer>}]’
recognizer_rtsp.cxx:348:76: required from here
/usr/include/c++/7/bits/invoke.h:89:5: error: no type named ‘type’ in ‘struct std::__invoke_result<Chronometer& (*)(Chronometer&), Chronometer*, std::reference_wrapper<Chronometer> >’
What kind of parameter should I pass through the thread ?
I went to several links to find a solution but nothing could solve my problem:
std::thread pass by reference calls copy constructor
No matching function to invoke, using std::thread
...
Chronometer::start_chrono is a static function, so it's not bound to any object, i.e doesn't need an object to called upon.
Static member functions are not associated with any object. When called, they have no this pointer.
You should have simply written.
std::thread(&Chronometer::start_chrono, std::ref(chrono));
GCC (5.3) & Clang (3.8) claim that the first line in test is bad, but the second one is fine. MSVC (2015.2) says, both are invalid.
template< typename N, typename T >
void f( N n, T t ) { std::get< n >( t ); }
void test() {
std::get< std::integral_constant< size_t, 0 >() >( std::make_tuple( 123 ) ); // not ok
f( std::integral_constant< size_t, 0 >(), std::make_tuple( 123 ) ); // ok for gcc, clang, but not msvc
}
What, exactly, according to the standard, is the difference? Is this code legal to begin with?
clang error for the first line:
In file included from main.cpp:2:
/usr/local/bin/../lib/gcc/x86_64-unknown-linux-gnu/5.3.0/../../../../include/c++/5.3.0/tuple:874:34: error: no matching function for call to '__get_helper2'
{ return std::forward<_Tp&&>(std::__get_helper2<_Tp>(__t)); }
^~~~~~~~~~~~~~~~~~~~~~~
main.cpp:10:10: note: in instantiation of function template specialization 'std::get<std::integral_constant<unsigned long, 0> (), int>' requested here
std::get<std::integral_constant<size_t, 0>()>( std::make_tuple( 123 ) ); // not ok
^
/usr/local/bin/../lib/gcc/x86_64-unknown-linux-gnu/5.3.0/../../../../include/c++/5.3.0/tuple:856:5: note: candidate template ignored: could not match '_Tuple_impl' against 'tuple'
__get_helper2(_Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
^
/usr/local/bin/../lib/gcc/x86_64-unknown-linux-gnu/5.3.0/../../../../include/c++/5.3.0/tuple:861:5: note: candidate template ignored: could not match '_Tuple_impl' against 'tuple'
__get_helper2(const _Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
^
1 error generated.
gcc error:
In file included from main.cpp:2:0:
/usr/local/include/c++/5.3.0/tuple: In instantiation of 'constexpr _Tp&& std::get(std::tuple<_Elements ...>&&) [with _Tp = std::integral_constant<long unsigned int, 0ul>(); _Types = {int}]':
main.cpp:10:75: required from here
/usr/local/include/c++/5.3.0/tuple:874:57: error: no matching function for call to '__get_helper2(std::tuple<int>&)'
{ return std::forward<_Tp&&>(std::__get_helper2<_Tp>(__t)); }
^
/usr/local/include/c++/5.3.0/tuple:856:5: note: candidate: template<class _Head, long unsigned int __i, class ... _Tail> constexpr _Head& std::__get_helper2(std::_Tuple_impl<__i, _Head, _Tail ...>&)
__get_helper2(_Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
^
/usr/local/include/c++/5.3.0/tuple:856:5: note: template argument deduction/substitution failed:
/usr/local/include/c++/5.3.0/tuple:874:57: note: mismatched types 'std::integral_constant<long unsigned int, 0ul>()' and 'int'
{ return std::forward<_Tp&&>(std::__get_helper2<_Tp>(__t)); }
^
/usr/local/include/c++/5.3.0/tuple:874:57: note: 'std::tuple<int>' is not derived from 'std::_Tuple_impl<__i, std::integral_constant<long unsigned int, 0ul>(), _Tail ...>'
/usr/local/include/c++/5.3.0/tuple:861:5: note: candidate: template<class _Head, long unsigned int __i, class ... _Tail> constexpr const _Head& std::__get_helper2(const std::_Tuple_impl<__i, _Head, _Tail ...>&)
__get_helper2(const _Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
^
/usr/local/include/c++/5.3.0/tuple:861:5: note: template argument deduction/substitution failed:
/usr/local/include/c++/5.3.0/tuple:874:57: note: mismatched types 'std::integral_constant<long unsigned int, 0ul>()' and 'int'
{ return std::forward<_Tp&&>(std::__get_helper2<_Tp>(__t)); }
^
/usr/local/include/c++/5.3.0/tuple:874:57: note: 'std::tuple<int>' is not derived from 'const std::_Tuple_impl<__i, std::integral_constant<long unsigned int, 0ul>(), _Tail ...>'
tl;dr I think gcc and clang's behavior in both cases is correct.
There is a subtle difference between your two calls. Let me just add an alias to illustrate:
using Zero = std::integral_constant<size_t, 0>;
auto tuple = std::make_tuple(123);
When you write:
std::get<Zero()>(tuple);
Zero() is a type. It is a nullary function returning a Zero. As such, you're calling the version of std::get that takes a type: std::get<T>(). Since there is no element in tuple that has type Zero(), this is an error.
On the other hand, when you write:
Zero n;
std::get<n>(tuple);
n is not a type - it is only ever a value. Since std::integral_constant has a constexpr operator size_t(), that one gets used and you end up calling std::get<I>(), which does what you'd expect.
The same could be accomplished by simply using brace initialization as well:
std::get<Zero{}>(tuple);
since Zero{} is definitely not a type.
I want something that's like unique_ptr, but guaranteed (within reason) to be non-null. I wrote this class that contains a unique_ptr, and I wrote this move constructor that I'd hoped would allow me to move-construct one of my pointers from another, as long as the underlying unique_ptr could be similarly move-constructed. So, I first try it with something simple; move-constructing a pointer-to-int from a pointer-to-int.
#include <memory>
#include <utility>
#include <cassert>
template<
typename T
>
class Nonup
{
private:
std::unique_ptr<T> m_ptr;
public:
explicit Nonup( T* p )
: m_ptr( p )
{ assert( p ); }
Nonup( const Nonup& ) = delete;
Nonup& operator=( const Nonup& ) = delete;
template<typename U>
Nonup( Nonup<U>&& old )
:
m_ptr( std::move( old ) )
{}
Nonup& operator=( Nonup&& rhs ) = default;
decltype( *m_ptr ) operator*() const { return *m_ptr; }
};
int main()
{
Nonup<int> first( new int( 42 ) );
Nonup<int> second( std::move( first ) );
return 0;
}
Why does g++ 4.7.0 give errors on the move-construction of the variable second? The output of "g++ -std=c++11 main.cpp" follows.
main.cpp: In instantiation of ‘Nonup<T>::Nonup(Nonup<U>&&) [with U = int; T = int]’:
main.cpp:40:43: required from here
main.cpp:27:37: error: no matching function for call to ‘std::unique_ptr<int, std::default_delete<int> >::unique_ptr(std::remove_reference<Nonup<int>&>::type)’
main.cpp:27:37: note: candidates are:
In file included from /usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/memory:86:0,
from main.cpp:1:
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:164:2: note: template<class _Up, class> std::unique_ptr::unique_ptr(std::auto_ptr<_Up>&&)
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:164:2: note: template argument deduction/substitution failed:
main.cpp:27:37: note: ‘std::remove_reference<Nonup<int>&>::type {aka Nonup<int>}’ is not derived from ‘std::auto_ptr<_Up>’
In file included from /usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/memory:86:0,
from main.cpp:1:
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:155:2: note: template<class _Up, class _Ep, class> std::unique_ptr::unique_ptr(std::unique_ptr<_Up, _Ep>&&)
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:155:2: note: template argument deduction/substitution failed:
main.cpp:27:37: note: ‘std::remove_reference<Nonup<int>&>::type {aka Nonup<int>}’ is not derived from ‘std::unique_ptr<_Up, _Ep>’
In file included from /usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/memory:86:0,
from main.cpp:1:
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:142:7: note: std::unique_ptr<_Tp, _Dp>::unique_ptr(std::unique_ptr<_Tp, _Dp>&&) [with _Tp = int; _Dp = std::default_delete<int>]
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:142:7: note: no known conversion for argument 1 from ‘std::remove_reference<Nonup<int>&>::type {aka Nonup<int>}’ to ‘std::unique_ptr<int, std::default_delete<int> >&&’
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:136:17: note: constexpr std::unique_ptr<_Tp, _Dp>::unique_ptr(std::nullptr_t) [with _Tp = int; _Dp = std::default_delete<int>; std::nullptr_t = std::nullptr_t]
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:136:17: note: no known conversion for argument 1 from ‘std::remove_reference<Nonup<int>&>::type {aka Nonup<int>}’ to ‘std::nullptr_t’
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:130:7: note: std::unique_ptr<_Tp, _Dp>::unique_ptr(std::unique_ptr<_Tp, _Dp>::pointer, typename std::remove_reference<_To>::type&&) [with _Tp = int; _Dp = std::default_delete<int>; std::unique_ptr<_Tp, _Dp>::pointer = int*; typename std::remove_reference<_To>::type = std::default_delete<int>]
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:130:7: note: candidate expects 2 arguments, 1 provided
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:125:7: note: std::unique_ptr<_Tp, _Dp>::unique_ptr(std::unique_ptr<_Tp, _Dp>::pointer, typename std::conditional<std::is_reference<_Dp>::value, _Dp, const _Dp&>::type) [with _Tp = int; _Dp = std::default_delete<int>; std::unique_ptr<_Tp, _Dp>::pointer = int*; typename std::conditional<std::is_reference<_Dp>::value, _Dp, const _Dp&>::type = const std::default_delete<int>&]
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:125:7: note: candidate expects 2 arguments, 1 provided
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:120:7: note: std::unique_ptr<_Tp, _Dp>::unique_ptr(std::unique_ptr<_Tp, _Dp>::pointer) [with _Tp = int; _Dp = std::default_delete<int>; std::unique_ptr<_Tp, _Dp>::pointer = int*]
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:120:7: note: no known conversion for argument 1 from ‘std::remove_reference<Nonup<int>&>::type {aka Nonup<int>}’ to ‘std::unique_ptr<int, std::default_delete<int> >::pointer {aka int*}’
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:114:17: note: constexpr std::unique_ptr<_Tp, _Dp>::unique_ptr() [with _Tp = int; _Dp = std::default_delete<int>]
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:114:17: note: candidate expects 0 arguments, 1 provided
Thanks!
You're trying to initialise m_ptr from the other Nonup, rather than its m_ptr. The move constructor's initialiser should be:
m_ptr( std::move( old.m_ptr ) )
^^^^^^
The following code compiles on gcc 4.6 but not 4.7. Is it 4.7's problem or 4.6's problem? Compiled with -std=gnu++0x.
#include <utility>
using namespace std;
struct Z {
};
struct X {
operator Z*() const { return nullptr; }
};
struct Y {
Y(Z*) {}
};
int main() {
pair<int, Y> p(make_pair(0, X()));
}
Error messages:
[hidden]$ g++-mp-4.6 -std=gnu++0x e.cpp
[hidden]$ g++-mp-4.7 -std=gnu++0x e.cpp
e.cpp: In function 'int main()':
e.cpp:17:37: error: no matching function for call to 'std::pair<int, Y>::pair(std::pair<int, X>)'
e.cpp:17:37: note: candidates are:
In file included from /opt/local/include/gcc47/c++/utility:72:0,
from e.cpp:1:
/opt/local/include/gcc47/c++/bits/stl_pair.h:204:9: note: template<class ... _Args1, long unsigned int ..._Indexes1, class ... _Args2, long unsigned int ..._Indexes2> std::pair::pair(std::tuple<_Args1 ...>&, std::tuple<_Args2 ...>&, std::_Index_tuple<_Indexes1 ...>, std::_Index_tuple<_Indexes2 ...>)
/opt/local/include/gcc47/c++/bits/stl_pair.h:204:9: note: template argument deduction/substitution failed:
e.cpp:17:37: note: 'std::pair<int, X>' is not derived from 'std::tuple<_Args1 ...>'
In file included from /opt/local/include/gcc47/c++/utility:72:0,
from e.cpp:1:
/opt/local/include/gcc47/c++/bits/stl_pair.h:153:9: note: template<class ... _Args1, class ... _Args2> std::pair::pair(std::piecewise_construct_t, std::tuple<_Args1 ...>, std::tuple<_Args2 ...>)
/opt/local/include/gcc47/c++/bits/stl_pair.h:153:9: note: template argument deduction/substitution failed:
e.cpp:17:37: note: cannot convert 'std::make_pair(_T1&&, _T2&&) [with _T1 = int; _T2 = X; typename std::__decay_and_strip<_T2>::__type = X; typename std::__decay_and_strip<_T1>::__type = int]((* & X()))' (type 'std::pair<int, X>') to type 'std::piecewise_construct_t'
In file included from /opt/local/include/gcc47/c++/utility:72:0,
from e.cpp:1:
/opt/local/include/gcc47/c++/bits/stl_pair.h:148:12: note: template<class _U1, class _U2, class> constexpr std::pair::pair(std::pair<_U1, _U2>&&)
/opt/local/include/gcc47/c++/bits/stl_pair.h:148:12: note: template argument deduction/substitution failed:
/opt/local/include/gcc47/c++/bits/stl_pair.h:145:38: error: no type named 'type' in 'struct std::enable_if<false, void>'
/opt/local/include/gcc47/c++/bits/stl_pair.h:142:12: note: template<class _U1, class _U2, class> constexpr std::pair::pair(_U1&&, _U2&&)
/opt/local/include/gcc47/c++/bits/stl_pair.h:142:12: note: template argument deduction/substitution failed:
e.cpp:17:37: note: candidate expects 2 arguments, 1 provided
In file included from /opt/local/include/gcc47/c++/utility:72:0,
from e.cpp:1:
/opt/local/include/gcc47/c++/bits/stl_pair.h:136:12: note: template<class _U2, class> constexpr std::pair::pair(const _T1&, _U2&&)
/opt/local/include/gcc47/c++/bits/stl_pair.h:136:12: note: template argument deduction/substitution failed:
e.cpp:17:37: note: cannot convert 'std::make_pair(_T1&&, _T2&&) [with _T1 = int; _T2 = X; typename std::__decay_and_strip<_T2>::__type = X; typename std::__decay_and_strip<_T1>::__type = int]((* & X()))' (type 'std::pair<int, X>') to type 'const int&'
In file included from /opt/local/include/gcc47/c++/utility:72:0,
from e.cpp:1:
/opt/local/include/gcc47/c++/bits/stl_pair.h:131:12: note: template<class _U1, class> constexpr std::pair::pair(_U1&&, const _T2&)
/opt/local/include/gcc47/c++/bits/stl_pair.h:131:12: note: template argument deduction/substitution failed:
e.cpp:17:37: note: candidate expects 2 arguments, 1 provided
In file included from /opt/local/include/gcc47/c++/utility:72:0,
from e.cpp:1:
/opt/local/include/gcc47/c++/bits/stl_pair.h:122:7: note: std::pair<_T1, _T2>::pair(std::pair<_T1, _T2>&&) [with _T1 = int; _T2 = Y; std::pair<_T1, _T2> = std::pair<int, Y>]
/opt/local/include/gcc47/c++/bits/stl_pair.h:122:7: note: no known conversion for argument 1 from 'std::pair<int, X>' to 'std::pair<int, Y>&&'
/opt/local/include/gcc47/c++/bits/stl_pair.h:119:17: note: constexpr std::pair<_T1, _T2>::pair(const std::pair<_T1, _T2>&) [with _T1 = int; _T2 = Y; std::pair<_T1, _T2> = std::pair<int, Y>]
/opt/local/include/gcc47/c++/bits/stl_pair.h:119:17: note: no known conversion for argument 1 from 'std::pair<int, X>' to 'const std::pair<int, Y>&'
/opt/local/include/gcc47/c++/bits/stl_pair.h:116:12: note: template<class _U1, class _U2, class> constexpr std::pair::pair(const std::pair<_U1, _U2>&)
/opt/local/include/gcc47/c++/bits/stl_pair.h:116:12: note: template argument deduction/substitution failed:
/opt/local/include/gcc47/c++/bits/stl_pair.h:113:38: error: no type named 'type' in 'struct std::enable_if<false, void>'
/opt/local/include/gcc47/c++/bits/stl_pair.h:104:26: note: constexpr std::pair<_T1, _T2>::pair(const _T1&, const _T2&) [with _T1 = int; _T2 = Y]
/opt/local/include/gcc47/c++/bits/stl_pair.h:104:26: note: candidate expects 2 arguments, 1 provided
/opt/local/include/gcc47/c++/bits/stl_pair.h:100:26: note: constexpr std::pair<_T1, _T2>::pair() [with _T1 = int; _T2 = Y]
/opt/local/include/gcc47/c++/bits/stl_pair.h:100:26: note: candidate expects 0 arguments, 1 provided
That shouldn't compile.
The initialisation of p.second requires an implicit conversion from X to Y. An implicit conversion can only involve at most one user-defined conversion The required conversion would require two; X to Z* via the conversion operator, and Z* to Y via the conversion constructor.
Initialisation of pair elements from another pair is only allowed via implicit conversions. C++11 says:
20.3.2/12 This constructor shall not participate in overload resolution unless const U& is implicitly convertible to first_type and const V& is implicitly convertible to second_type.
and C++98 said:
20.2.2/4 Initializes members from the corresponding members of the argument, performing implicit conversions as needed.
Presumably, the older version had a bug which allowed this conversion to be considered, and that bug has been fixed in the more recent version.