c++ functional / std::bind doesn't compile with Apple Clang - xcode

Here is a short version of the code I try to compile.
#include <iostream>
#include <functional>
#include <memory>
void foo(std::shared_ptr<int> b, unsigned int i)
{
std::cout << *b << " - " << i << std::endl;
}
int main()
{
using namespace std::placeholders;
typedef std::function<void(std::shared_ptr<int> b, unsigned int i)> Foo;
typedef std::function<void(unsigned int code)> Bar;
Foo f1 = foo;
Bar f2 = std::bind(f1, std::make_shared<int>(10), _1);
f2(0);
return 0;
}
g++-4.7 --version gives g++-4.7 (GCC) 4.7.1
g++-4.7 -std=c++11 test.cpp && ./a.out
10 - 0
c++ --version gives Apple clang version 4.0 (tags/Apple/clang-421.0.60) (based on LLVM 3.1svn)
c++ -std=c++11 -stdlib=libc++ test.cpp
In file included from test.cpp:3:
In file included from /usr/bin/../lib/c++/v1/iostream:38:
In file included from /usr/bin/../lib/c++/v1/ios:216:
In file included from /usr/bin/../lib/c++/v1/__locale:18:
In file included from /usr/bin/../lib/c++/v1/mutex:177:
/usr/bin/../lib/c++/v1/functional:1642:8: error: no type named 'type' in 'std::__1::__invoke_of<std::__1::function<void (std::__1::shared_ptr<int>, unsigned int)> &,
std::__1::shared_ptr<int> &, std::__1::shared_ptr<int> &&>'
>::type type;
~~~^~~~
/usr/bin/../lib/c++/v1/functional:1721:18: note: in instantiation of template class 'std::__1::__bind_return<std::__1::function<void (std::__1::shared_ptr<int>, unsigned int)>,
std::__1::tuple<std::__1::shared_ptr<int>, std::__1::placeholders::__ph<1>>, std::__1::tuple<std::__1::shared_ptr<int> &&, unsigned int &&>>' requested here
typename __bind_return<_Fd, _Td, tuple<_Args&&...> >::type
^
/usr/bin/../lib/c++/v1/functional:1722:9: note: while substituting deduced template arguments into function template 'operator()'
[with _Args = <std::__1::shared_ptr<int>, unsigned int>]
operator()(_Args&& ...__args)
^
/usr/bin/../lib/c++/v1/type_traits:2971:1: note: while substituting deduced template arguments into function template '__invoke' [with _Fp = std::__1::__bind<std::__1::function<void
(std::__1::shared_ptr<int>, unsigned int)> &, std::__1::shared_ptr<int>, std::__1::placeholders::__ph<1> &> &, _Args = <no value>]
__invoke(_Fp&& __f, _Args&& ...__args)
^
/usr/bin/../lib/c++/v1/type_traits:2989:11: note: in instantiation of template class 'std::__1::__invokable_imp<std::__1::__bind<std::__1::function<void
(std::__1::shared_ptr<int>, unsigned int)> &, std::__1::shared_ptr<int>, std::__1::placeholders::__ph<1> &> &, std::__1::shared_ptr<int>, unsigned int>' requested here
__invokable_imp<_Fp, _Args...>::value>
^
/usr/bin/../lib/c++/v1/functional:1115:33: note: in instantiation of template class 'std::__1::__invokable<std::__1::__bind<std::__1::function<void
(std::__1::shared_ptr<int>, unsigned int)> &, std::__1::shared_ptr<int>, std::__1::placeholders::__ph<1> &> &, std::__1::shared_ptr<int>, unsigned int>' requested here
template <class _Fp, bool = __invokable<_Fp&, _ArgTypes...>::value>
^
/usr/bin/../lib/c++/v1/functional:1141:35: note: (skipping 13 contexts in backtrace; use -ftemplate-backtrace-limit=0 to see all)
typename enable_if<__callable<_Fp>::value>::type* = 0);
^
/usr/bin/../lib/c++/v1/memory:2218:20: note: in instantiation of template class 'std::__1::is_nothrow_move_constructible<std::__1::__bind<std::__1::function<void
(std::__1::shared_ptr<int>, unsigned int)> &, std::__1::shared_ptr<int>, std::__1::placeholders::__ph<1> &>>' requested here
_NOEXCEPT_(is_nothrow_move_constructible<_T1>::value &&
^
/usr/bin/../lib/c++/v1/__config:253:34: note: expanded from macro '_NOEXCEPT_'
# define _NOEXCEPT_(x) noexcept(x)
^
/usr/bin/../lib/c++/v1/memory:2386:15: note: in instantiation of template class 'std::__1::__libcpp_compressed_pair_imp<std::__1::__bind<std::__1::function<void
(std::__1::shared_ptr<int>, unsigned int)> &, std::__1::shared_ptr<int>, std::__1::placeholders::__ph<1> &>, std::__1::allocator<std::__1::__bind<std::__1::function<void
(std::__1::shared_ptr<int>, unsigned int)> &, std::__1::shared_ptr<int>, std::__1::placeholders::__ph<1> &>>, 2>' requested here
: private __libcpp_compressed_pair_imp<_T1, _T2>
^
/usr/bin/../lib/c++/v1/functional:988:36: note: in instantiation of template class 'std::__1::__compressed_pair<std::__1::__bind<std::__1::function<void
(std::__1::shared_ptr<int>, unsigned int)> &, std::__1::shared_ptr<int>, std::__1::placeholders::__ph<1> &>, std::__1::allocator<std::__1::__bind<std::__1::function<void
(std::__1::shared_ptr<int>, unsigned int)> &, std::__1::shared_ptr<int>, std::__1::placeholders::__ph<1> &>>>' requested here
__compressed_pair<_Fp, _Alloc> __f_;
^
/usr/bin/../lib/c++/v1/functional:1273:13: note: in instantiation of template class 'std::__1::__function::__func<std::__1::__bind<std::__1::function<void
(std::__1::shared_ptr<int>, unsigned int)> &, std::__1::shared_ptr<int>, std::__1::placeholders::__ph<1> &>, std::__1::allocator<std::__1::__bind<std::__1::function<void
(std::__1::shared_ptr<int>, unsigned int)> &, std::__1::shared_ptr<int>, std::__1::placeholders::__ph<1> &>>, void (unsigned int)>' requested here
if (sizeof(_FF) <= sizeof(__buf_) && is_nothrow_copy_constructible<_Fp>::value)
^
test.cpp:21:12: note: in instantiation of function template specialization 'std::__1::function<void (unsigned int)>::function<std::__1::__bind<std::__1::function<void
(std::__1::shared_ptr<int>, unsigned int)> &, std::__1::shared_ptr<int>, std::__1::placeholders::__ph<1> &> >' requested here
Bar f2 = std::bind(f1, std::make_shared<int>(10), _1);
^
1 error generated.
Is there something wrong with my code?
Thanks.

Sorry about the bug.
This looks like a duplicate of:
http://llvm.org/bugs/show_bug.cgi?id=15295
Here is a patch that fixes it:
Index: include/functional
===================================================================
--- include/functional (revision 175515)
+++ include/functional (working copy)
## -1624,16 +1624,38 ##
: public ____mu_return<_Ti,
__is_reference_wrapper<_Ti>::value,
is_bind_expression<_Ti>::value,
- 0 < is_placeholder<_Ti>::value,
+ 0 < is_placeholder<_Ti>::value &&
+ is_placeholder<_Ti>::value <= tuple_size<_TupleUj>::value,
_TupleUj>
{
};
template <class _Fp, class _BoundArgs, class _TupleUj>
+struct _is_valid_bind_return
+{
+ static const bool value = false;
+};
+
+template <class _Fp, class ..._BoundArgs, class _TupleUj>
+struct _is_valid_bind_return<_Fp, tuple<_BoundArgs...>, _TupleUj>
+{
+ static const bool value = __invokable<_Fp,
+ typename __mu_return<_BoundArgs, _TupleUj>::type...>::value;
+};
+
+template <class _Fp, class ..._BoundArgs, class _TupleUj>
+struct _is_valid_bind_return<_Fp, const tuple<_BoundArgs...>, _TupleUj>
+{
+ static const bool value = __invokable<_Fp,
+ typename __mu_return<const _BoundArgs, _TupleUj>::type...>::value;
+};
+
+template <class _Fp, class _BoundArgs, class _TupleUj,
+ bool = _is_valid_bind_return<_Fp, _BoundArgs, _TupleUj>::value>
struct __bind_return;
template <class _Fp, class ..._BoundArgs, class _TupleUj>
-struct __bind_return<_Fp, tuple<_BoundArgs...>, _TupleUj>
+struct __bind_return<_Fp, tuple<_BoundArgs...>, _TupleUj, true>
{
typedef typename __invoke_of
<
## -1647,7 +1669,7 ##
};
template <class _Fp, class ..._BoundArgs, class _TupleUj>
-struct __bind_return<_Fp, const tuple<_BoundArgs...>, _TupleUj>
+struct __bind_return<_Fp, const tuple<_BoundArgs...>, _TupleUj, true>
{
typedef typename __invoke_of
<
## -1673,8 +1695,10 ##
class __bind
: public __weak_result_type<typename decay<_Fp>::type>
{
+protected:
typedef typename decay<_Fp>::type _Fd;
typedef tuple<typename decay<_BoundArgs>::type...> _Td;
+private:
_Fd __f_;
_Td __bound_args_;
## -1731,7 +1755,7 ##
template <class ..._Args>
_LIBCPP_INLINE_VISIBILITY
- typename __bind_return<_Fd, _Td, tuple<_Args&&...> >::type
+ typename __bind_return<const _Fd, const _Td, tuple<_Args&&...> >::type
operator()(_Args&& ...__args) const
{
return __apply_functor(__f_, __bound_args_, __indices(),
## -1747,6 +1771,8 ##
: public __bind<_Fp, _BoundArgs...>
{
typedef __bind<_Fp, _BoundArgs...> base;
+ typedef typename base::_Fd _Fd;
+ typedef typename base::_Td _Td;
public:
typedef _Rp result_type;
## -1784,7 +1810,12 ##
template <class ..._Args>
_LIBCPP_INLINE_VISIBILITY
- result_type
+ typename enable_if
+ <
+ is_convertible<typename __bind_return<_Fd, _Td, tuple<_Args&&...> >::type,
+ result_type>::value,
+ result_type
+ >::type
operator()(_Args&& ...__args)
{
return base::operator()(_VSTD::forward<_Args>(__args)...);
## -1792,7 +1823,12 ##
template <class ..._Args>
_LIBCPP_INLINE_VISIBILITY
- result_type
+ typename enable_if
+ <
+ is_convertible<typename __bind_return<const _Fd, const _Td, tuple<_Args&&...> >::type,
+ result_type>::value,
+ result_type
+ >::type
operator()(_Args&& ...__args) const
{
return base::operator()(_VSTD::forward<_Args>(__args)...);

It works on Ubuntu (listdc++ instead of libc++) with clang 3.2, so it's not issue in your code.

Related

Error in constexpr' expansion of 'shader.base::BasicStringPiece<char>::remove_prefix(6)'

constexpr base::StringPiece StripLambda(base::StringPiece shader) {
// Must contain at least "[]() {}".
DCHECK_EQ(shader.substr(0, 6), "[]() {");
DCHECK_EQ(shader.back(), '}');
shader.remove_prefix(6);
shader.remove_suffix(1);
return shader;
}
chromium94/src/components/viz/service/display/shader.cc:29:23: in 'constexpr' expansion of 'shader.base::BasicStringPiece::remove_prefix(6)'
chromium94/src/base/check_op.h:157:41: error: 'constexpr logging::CheckOpResult logging::CheckLEImpl(T, U, const char*) [with T = unsigned int; U = unsigned int; typename std::enable_if<(std::is_fundamental<_Tp>::value && std::is_fundamental::value), int>::type = 0]' called in a constant expression
chromium94/src/base/check_op.h:184:38: error: call to non-'constexpr' function 'logging::CheckOpResult::CheckOpResult(const char*, char*, char*)'
chromium94/src/base/check_op.h:157:41: error: 'constexpr logging::CheckOpResult logging::CheckLEImpl(T, U, const char*) [with T = unsigned int; U = unsigned int; typename std::enable_if<(std::is_fundamental<_Tp>::value && std::is_fundamental::value), int>::type = 0]' called in a constant expression
Can anyone help with work around solution?
Can anyone help with work around solution?

How to get *any* example of boost::mpl::map working?

Here is my sample code. Can someone please help me with it?
#include <string>
#include <utility> //Not strictly necessary (gets imported implicitely anyway)
#include <boost/mpl/map.hpp>
#include <boost/mpl/size.hpp>
#include <boost/type_traits/is_same.hpp>
typedef boost::mpl::map<
std::pair<int,unsigned>
, std::pair<char,unsigned char>
> m;
int main()
{
std::pair<int,unsigned> b(10,10); //this works
int a = boost::mpl::size<m>::value; //this doesn't
}
The error message:
In file included from /home/adam/spack/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/boost-1.67.0-xcr4z3warx5tptvihmi5biqrq7hpgw7j/include/boost/mpl/map/aux_/include_preprocessed.hpp:47:0,
from /home/adam/spack/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/boost-1.67.0-xcr4z3warx5tptvihmi5biqrq7hpgw7j/include/boost/mpl/map/map10.hpp:28,
from /home/adam/spack/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/boost-1.67.0-xcr4z3warx5tptvihmi5biqrq7hpgw7j/include/boost/mpl/map/map20.hpp:19,
from /home/adam/spack/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/boost-1.67.0-xcr4z3warx5tptvihmi5biqrq7hpgw7j/include/boost/mpl/map.hpp:36,
from /home/adam/c++/tests/simple_test/test2.cpp:3:
/home/adam/spack/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/boost-1.67.0-xcr4z3warx5tptvihmi5biqrq7hpgw7j/include/boost/mpl/map/aux_/preprocessed/typeof_based/map10.hpp: In instantiation of ‘struct boost::mpl::map2<std::pair<int, unsigned int>, std::pair<char, unsigned char> >’:
/home/adam/spack/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/boost-1.67.0-xcr4z3warx5tptvihmi5biqrq7hpgw7j/include/boost/mpl/aux_/preprocessed/gcc/map.hpp:51:8: required from ‘struct boost::mpl::map<std::pair<int, unsigned int>, std::pair<char, unsigned char> >’
/home/adam/spack/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/boost-1.67.0-xcr4z3warx5tptvihmi5biqrq7hpgw7j/include/boost/mpl/aux_/has_tag.hpp:20:1: required by substitution of ‘template<class U> static char (& boost::mpl::aux::has_tag<boost::mpl::map<std::pair<int, unsigned int>, std::pair<char, unsigned char> >, mpl_::bool_<false> >::gcc_3_2_wknd::test<U>(const volatile boost::mpl::aux::type_wrapper<T>*, boost::mpl::aux::type_wrapper<typename U::tag>*))[2] [with U = boost::mpl::map<std::pair<int, unsigned int>, std::pair<char, unsigned char> >]’
/home/adam/spack/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/boost-1.67.0-xcr4z3warx5tptvihmi5biqrq7hpgw7j/include/boost/mpl/aux_/has_tag.hpp:20:1: required from ‘const bool boost::mpl::aux::has_tag<boost::mpl::map<std::pair<int, unsigned int>, std::pair<char, unsigned char> >, mpl_::bool_<false> >::value’
/home/adam/spack/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/boost-1.67.0-xcr4z3warx5tptvihmi5biqrq7hpgw7j/include/boost/mpl/aux_/has_tag.hpp:20:1: required from ‘struct boost::mpl::aux::has_tag<boost::mpl::map<std::pair<int, unsigned int>, std::pair<char, unsigned char> >, mpl_::bool_<false> >’
/home/adam/spack/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/boost-1.67.0-xcr4z3warx5tptvihmi5biqrq7hpgw7j/include/boost/mpl/sequence_tag.hpp:110:8: required from ‘struct boost::mpl::sequence_tag<boost::mpl::map<std::pair<int, unsigned int>, std::pair<char, unsigned char> > >’
/home/adam/spack/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/boost-1.67.0-xcr4z3warx5tptvihmi5biqrq7hpgw7j/include/boost/mpl/size.hpp:29:8: required from ‘struct boost::mpl::size<boost::mpl::map<std::pair<int, unsigned int>, std::pair<char, unsigned char> > >’
/home/adam/c++/tests/simple_test/test2.cpp:15:29: required from here
/home/adam/spack/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/boost-1.67.0-xcr4z3warx5tptvihmi5biqrq7hpgw7j/include/boost/mpl/map/aux_/preprocessed/typeof_based/map10.hpp:31:8: error: no type named ‘first’ in ‘struct std::pair<char, unsigned char>’
struct map2
^~~~
In file included from /home/adam/c++/tests/simple_test/test2.cpp:4:0:
/home/adam/spack/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/boost-1.67.0-xcr4z3warx5tptvihmi5biqrq7hpgw7j/include/boost/mpl/size.hpp: In instantiation of ‘struct boost::mpl::size<boost::mpl::map<std::pair<int, unsigned int>, std::pair<char, unsigned char> > >’:
/home/adam/c++/tests/simple_test/test2.cpp:15:29: required from here
/home/adam/spack/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/boost-1.67.0-xcr4z3warx5tptvihmi5biqrq7hpgw7j/include/boost/mpl/size.hpp:29:8: error: no class template named ‘apply’ in ‘struct boost::mpl::size_impl<boost::mpl::non_sequence_tag>’
struct size
^~~~
/home/adam/c++/tests/simple_test/test2.cpp: In function ‘int main()’:
/home/adam/c++/tests/simple_test/test2.cpp:15:31: error: ‘value’ is not a member of ‘boost::mpl::size<boost::mpl::map<std::pair<int, unsigned int>, std::pair<char, unsigned char> > >’
int a = boost::mpl::size<m>::value; //this doesn't
^~~~~
/home/adam/c++/tests/simple_test/test2.cpp:15:6: warning: unused variable ‘a’ [-Wunused-variable]
int a = boost::mpl::size<m>::value; //this doesn't
^
CMakeFiles/libsimple_test.dir/build.make:62: recipe for target 'CMakeFiles/libsimple_test.dir/test2.cpp.o' failed
make[2]: *** [CMakeFiles/libsimple_test.dir/test2.cpp.o] Error 1
CMakeFiles/Makefile2:142: recipe for target 'CMakeFiles/libsimple_test.dir/all' failed
make[1]: *** [CMakeFiles/libsimple_test.dir/all] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2
I use C++11 on GCC 7.3.0 and libboost 1.67.0 on Ubuntu 16.04 64bit.
By chance I found a solution: Don't use the standard std::pair, but rather use the re-invented boost::mpl::pair. After simple replacing std::pair into boost::mpl::pair the sample code compiles and runs properly... which leads to another question.

std::get on std::tuple results in variadic args reducing to nothing with incomplete type error

The following code produces a huge list of compiler errors:
/// Uses template recursion to bind all args
template<std::size_t N, typename... Args> class Binder
{
public:
Binder(Sqlite3StatementBase &s, std::tuple<Args...> &tup)
{
Binder<N - 1, Args...> b(s, tup);
s.bind(N + 1, std::get<N, Args...>(tup)); // Line 182
}
};
/// Specialization of Binder to end recursion at 0
template<typename... Args> class Binder<0, Args...>
{
public:
Binder(Sqlite3StatementBase &s, std::tuple<Args...> &tup)
{
s.bind(1, std::get<0, Args...>(tup));
}
};
The first batch of errors consists of:
In file included from /usr/include/c++/6/bits/unique_ptr.h:37:0,
from /usr/include/c++/6/condition_variable:43,
from /home/tony/htpc/Dev/logi/src/db/logi-db.h:22,
from /home/tony/htpc/Dev/logi/src/db/logi-sqlite.h:26,
from /home/tony/htpc/Dev/logi/src/db/logi-sqlite.cpp:24:
/usr/include/c++/6/tuple: In instantiation of ‘class std::tuple_element<1ul, std::tuple<unsigned int> >’:
/usr/include/c++/6/tuple:1228:12: recursively required from ‘class std::tuple_element<2ul, std::tuple<unsigned int, unsigned int> >’
/usr/include/c++/6/tuple:1228:12: required from ‘class std::tuple_element<3ul, std::tuple<unsigned int, unsigned int, unsigned int> >’
/usr/include/c++/6/utility:106:69: required by substitution of ‘template<long unsigned int __i, class _Tp> using __tuple_element_t = typename std::tuple_element::type [with long unsigned int __i = 3ul; _Tp = std::tuple<unsigned int, unsigned int, unsigned int>]’
/usr/include/c++/6/tuple:1270:5: required by substitution of ‘template<long unsigned int __i, class ... _Elements> constexpr std::__tuple_element_t<__i, std::tuple<_Elements ...> >&& std::get(std::tuple<_Elements ...>&&) [with long unsigned int __i = 3ul; _Elements = {unsigned int, unsigned int, unsigned int}]’
/home/tony/htpc/Dev/logi/src/db/logi-sqlite.h:182:47: required from ‘logi::Sqlite3Database::Binder<N, Args>::Binder(logi::Sqlite3Database::Sqlite3StatementBase&, std::tuple<_Elements ...>&) [with long unsigned int N = 3ul; Args = {unsigned int, unsigned int, unsigned int}]’
/home/tony/htpc/Dev/logi/src/db/logi-sqlite.h:238:71: required from ‘void logi::Sqlite3Database::Sqlite3Statement<Args>::prepare_row(logi::Sqlite3Database::Sqlite3Statement<Args>::Tup&) [with Args = {unsigned int, unsigned int, unsigned int}; logi::Sqlite3Database::Sqlite3Statement<Args>::Tup = std::tuple<unsigned int, unsigned int, unsigned int>]’
/home/tony/htpc/Dev/logi/src/db/logi-sqlite.h:231:28: required from ‘void logi::Sqlite3Database::Sqlite3Statement<Args>::execute(typename logi::Sqlite3Database::Sqlite3Statement<Args>::Parent::ArgsVector&) [with Args = {unsigned int, unsigned int, unsigned int}; typename logi::Sqlite3Database::Sqlite3Statement<Args>::Parent::ArgsVector = std::vector<std::tuple<unsigned int, unsigned int, unsigned int>, std::allocator<std::tuple<unsigned int, unsigned int, unsigned int> > >]’
/home/tony/htpc/Dev/logi/src/db/logi-sqlite.cpp:354:1: required from here
/usr/include/c++/6/tuple:1228:12: error: invalid use of incomplete type ‘class std::tuple_element<0ul, std::tuple<> >’
So it seems as if the std::get call is causing other parts of the system libraries (not directly related to std::get or std::tuple) to recursively reduce Args... to nothing, and this is happening independently of my recursion of the numerical template parameter N. Is there something I can fix in my code without fundamentally changing my approach, or is it just not possible to use std::get in a context where the tuple's template parameters are variadic?
Given an implementation of the C++14 make_index_sequence function (and its associated types), you can do what you want easily enough:
template<size_t ...indices, typename ...Args>
void binder_helper(Sqlite3StatementBase &s, std::integer_sequence<size_t, indices...>, std::tuple<Args...> &tup)
{
auto dump = {(s.bind(indices, std::get<indices>(tup)), 0)...};
}
template<typename ...Args>
void binder(Sqlite3StatementBase &s, std::tuple<Args...> &tup)
{
binder_helper(s, std::make_index_sequence<sizeof...(Args)>(), tup);
}
With C++17's fold expressions, the oddball stuff in binder_helper can be reduced to something much more reasonable:
template<size_t ...indices, typename ...Args>
void binder_helper(Sqlite3StatementBase &s, std::integer_sequence<size_t, indices...>, std::tuple<Args...> &tup)
{
(s.bind(indices, std::get<indices>(tup)), ...);
}
Note that in the latter case, the standard does not guarantee thatt the calls to s.bind will be executed in order. In the former case, because the expressions are wrapped in a braced-init-list, you're guaranteed in-order evaluation.

unordered_map with IP address as a key

I am trying to build a list of linked list in my application. The list will contains unique IP addresses,and for each IP addres I have a list of applications. I am trying to build it using unordered_map to take Boost::boost::asio::ip::address as a the key and std::list as value:
#include <boost/unordered/unordered_map.hpp>
#include <iostream>
#include <list>
using namespace boost::asio::ip;
using namespace std;
typedef int ApplicationID;
typedef address IPAddress;
typedef list <ApplicationID> APP_LIST;
typedef boost::unordered::unordered_map <IPAddress, APP_LIST> USER_MAP;
USER_MAP user_map;
Later I try to get the list associated with an IP address as following:
APP_LIST *list = &user_map[ip];
But I get errors in the compilation, so could you please specify what's the problem?
Is it possible to use Boost:IPaddress as a key function?
Another question is it possible to use char[some_size] as a key value?
Error Output:
In file included from /boost/functional/hash/hash.hpp:535:0,
from /boost/functional/hash.hpp:6,
from /boost/unordered/unordered_map.hpp:21,
from ipc_module.cpp:18:
/boost/functional/hash/extensions.hpp: In member function ‘std::size_t boost::hash<T>::operator()(const T&) const [with T = boost::asio::ip::address, std::size_t = long unsigned int]’:
/boost/unordered/detail/unique.hpp:331:55: instantiated from ‘boost::unordered::detail::table_impl<Types>::value_type& boost::unordered::detail::table_impl<Types>::operator[](const key_type&) [with Types = boost::unordered::detail::map<std::allocator<std::pair<const boost::asio::ip::address, std::list<int> > >, boost::asio::ip::address, std::list<int>, boost::hash<boost::asio::ip::address>, std::equal_to<boost::asio::ip::address> >, boost::unordered::detail::table_impl<Types>::value_type = std::pair<const boost::asio::ip::address, std::list<int> >, boost::unordered::detail::table_impl<Types>::key_type = boost::asio::ip::address]’
/boost/unordered/unordered_map.hpp:1192:26: instantiated from ‘boost::unordered::unordered_map<K, T, H, P, A>::mapped_type& boost::unordered::unordered_map<K, T, H, P, A>::operator[](const key_type&) [with K = boost::asio::ip::address, T = std::list<int>, H = boost::hash<boost::asio::ip::address>, P = std::equal_to<boost::asio::ip::address>, A = std::allocator<std::pair<const boost::asio::ip::address, std::list<int> > >, boost::unordered::unordered_map<K, T, H, P, A>::mapped_type = std::list<int>, boost::unordered::unordered_map<K, T, H, P, A>::key_type = boost::asio::ip::address]’
ipc_module.cpp:175:40: instantiated from here
/boost/functional/hash/extensions.hpp:176:34: error: no matching function for call to ‘hash_value(const boost::asio::ip::address&)’
/boost/functional/hash/extensions.hpp:176:34: note: candidates are:
/boost/smart_ptr/shared_ptr.hpp:708:33: note: template<class T> std::size_t boost::hash_value(const boost::shared_ptr<T>&)
/boost/functional/hash/hash.hpp:144:24: note: std::size_t boost::hash_value(bool)
/boost/functional/hash/hash.hpp:144:24: note: no known conversion for argument 1 from ‘const boost::asio::ip::address’ to ‘bool’
/boost/functional/hash/hash.hpp:149:24: note: std::size_t boost::hash_value(char)
/boost/functional/hash/hash.hpp:149:24: note: no known conversion for argument 1 from ‘const boost::asio::ip::address’ to ‘char’
/boost/functional/hash/hash.hpp:154:24: note: std::size_t boost::hash_value(unsigned char)
/boost/functional/hash/hash.hpp:154:24: note: no known conversion for argument 1 from ‘const boost::asio::ip::address’ to ‘unsigned char’
/boost/functional/hash/hash.hpp:159:24: note: std::size_t boost::hash_value(signed char)
/boost/functional/hash/hash.hpp:159:24: note: no known conversion for argument 1 from ‘const boost::asio::ip::address’ to ‘signed char’
/boost/functional/hash/hash.hpp:164:24: note: std::size_t boost::hash_value(short int)
/boost/functional/hash/hash.hpp:164:24: note: no known conversion for argument 1 from ‘const boost::asio::ip::address’ to ‘short int’
/boost/functional/hash/hash.hpp:169:24: note: std::size_t boost::hash_value(short unsigned int)
/boost/functional/hash/hash.hpp:169:24: note: no known conversion for argument 1 from ‘const boost::asio::ip::address’ to ‘short unsigned int’
/boost/functional/hash/hash.hpp:174:24: note: std::size_t boost::hash_value(int)
/boost/functional/hash/hash.hpp:174:24: note: no known conversion for argument 1 from ‘const boost::asio::ip::address’ to ‘int’
/boost/functional/hash/hash.hpp:179:24: note: std::size_t boost::hash_value(unsigned int)
/boost/functional/hash/hash.hpp:179:24: note: no known conversion for argument 1 from ‘const boost::asio::ip::address’ to ‘unsigned int’
/boost/functional/hash/hash.hpp:184:24: note: std::size_t boost::hash_value(long int)
/boost/functional/hash/hash.hpp:184:24: note: no known conversion for argument 1 from ‘const boost::asio::ip::address’ to ‘long int’
/boost/functional/hash/hash.hpp:189:24: note: std::size_t boost::hash_value(long unsigned int)
/boost/functional/hash/hash.hpp:189:24: note: no known conversion for argument 1 from ‘const boost::asio::ip::address’ to ‘long unsigned int’
/boost/functional/hash/hash.hpp:195:24: note: std::size_t boost::hash_value(wchar_t)
/boost/functional/hash/hash.hpp:195:24: note: no known conversion for argument 1 from ‘const boost::asio::ip::address’ to ‘wchar_t’
/boost/functional/hash/hash.hpp:202:24: note: std::size_t boost::hash_value(boost::long_long_type)
/boost/functional/hash/hash.hpp:202:24: note: no known conversion for argument 1 from ‘const boost::asio::ip::address’ to ‘boost::long_long_type {aka long long int}’
/boost/functional/hash/hash.hpp:207:24: note: std::size_t boost::hash_value(boost::ulong_long_type)
/boost/functional/hash/hash.hpp:207:24: note: no known conversion for argument 1 from ‘const boost::asio::ip::address’ to ‘boost::ulong_long_type {aka long long unsigned int}’
/boost/functional/hash/hash.hpp:215:36: note: template<class T> std::size_t boost::hash_value(T* const&)
/boost/functional/hash/hash.hpp:308:24: note: template<class T, unsigned int N> std::size_t boost::hash_value(const T (&)[N])
/boost/functional/hash/hash.hpp:314:24: note: template<class T, unsigned int N> std::size_t boost::hash_value(T (&)[N])
/boost/functional/hash/hash.hpp:327:24: note: std::size_t boost::hash_value(float)
/boost/functional/hash/hash.hpp:327:24: note: no known conversion for argument 1 from ‘const boost::asio::ip::address’ to ‘float’
/boost/functional/hash/hash.hpp:332:24: note: std::size_t boost::hash_value(double)
/boost/functional/hash/hash.hpp:332:24: note: no known conversion for argument 1 from ‘const boost::asio::ip::address’ to ‘double’
/boost/functional/hash/hash.hpp:337:24: note: std::size_t boost::hash_value(long double)
/boost/functional/hash/hash.hpp:337:24: note: no known conversion for argument 1 from ‘const boost::asio::ip::address’ to ‘long double’
/boost/functional/hash/hash.hpp:321:24: note: template<class Ch, class A> std::size_t boost::hash_value(const std::basic_string<Ch, std::char_traits<_CharT>, A>&)
/boost/functional/hash/hash.hpp:343:24: note: std::size_t boost::hash_value(std::type_index)
/boost/functional/hash/hash.hpp:343:24: note: no known conversion for argument 1 from ‘const boost::asio::ip::address’ to ‘std::type_index’
/boost/functional/hash/extensions.hpp:54:17: note: template<class A, class B> std::size_t boost::hash_value(const std::pair<_T1, _T2>&)
/boost/functional/hash/extensions.hpp:63:17: note: template<class T, class A> std::size_t boost::hash_value(const std::vector<_Tp, _Alloc>&)
/boost/functional/hash/extensions.hpp:69:17: note: template<class T, class A> std::size_t boost::hash_value(const std::list<_Tp, _Alloc>&)
/boost/functional/hash/extensions.hpp:75:17: note: template<class T, class A> std::size_t boost::hash_value(const std::deque<_Tp, _Alloc>&)
/boost/functional/hash/extensions.hpp:81:17: note: template<class K, class C, class A> std::size_t boost::hash_value(const std::set<_Key, _Compare, _Alloc>&)
/boost/functional/hash/extensions.hpp:87:17: note: template<class K, class C, class A> std::size_t boost::hash_value(const std::multiset<_Key, _Compare, _Alloc>&)
/boost/functional/hash/extensions.hpp:93:17: note: template<class K, class T, class C, class A> std::size_t boost::hash_value(const std::map<_Key, _Tp, _Compare, _Alloc>&)
/boost/functional/hash/extensions.hpp:99:17: note: template<class K, class T, class C, class A> std::size_t boost::hash_value(const std::multimap<_Key, _Tp, _Compare, _Alloc>&)
/boost/functional/hash/extensions.hpp:105:17: note: template<class T> std::size_t boost::hash_value(const std::complex<_Tp>&)
/boost/functional/hash/extensions.hpp:177:9: warning: control reaches end of non-void function [-Wreturn-type]
/boost/asio/error.hpp: At global scope:
/boost/asio/error.hpp:244:45: warning: ‘boost::asio::error::system_category’ defined but not used [-Wunused-variable]
/boost/asio/error.hpp:246:45: warning: ‘boost::asio::error::netdb_category’ defined but not used [-Wunused-variable]
/boost/asio/error.hpp:248:45: warning: ‘boost::asio::error::addrinfo_category’ defined but not used [-Wunused-variable]
/boost/asio/error.hpp:250:45: warning: ‘boost::asio::error::misc_category’ defined but not used [-Wunused-variable]
Here's what I came up with after a brief inspection of the class interface for ip::address.
I would like to note that it's pretty wasteful to use. Especially if you happen to know that all addresses are ipv4, e.g. I'd prefer to key by ulong then.
namespace boost
{
template <>
struct hash<IPAddress>
{
size_t operator()(IPAddress const& v) const {
if (v.is_v4())
return v.to_v4().to_ulong();
if (v.is_v6())
{
auto const& range = v.to_v6().to_bytes();
return hash_range(range.begin(), range.end());
}
if (v.is_unspecified())
{
// guaranteed to be random: chosen by fair dice roll
return static_cast<size_t>(0x4751301174351161ul);
}
return hash_value(v.to_string());
}
};
}
See it Live on Coliru:
#include <boost/asio.hpp>
#include <boost/unordered/unordered_map.hpp>
#include <iostream>
#include <list>
typedef int ApplicationID;
typedef boost::asio::ip::address IPAddress;
typedef std::list<ApplicationID> APP_LIST;
typedef boost::unordered::unordered_map<IPAddress, APP_LIST> USER_MAP;
namespace boost
{
template <>
struct hash<IPAddress>
{
size_t operator()(IPAddress const& v) const {
if (v.is_v4())
return v.to_v4().to_ulong();
if (v.is_v6())
{
auto const& range = v.to_v6().to_bytes();
return hash_range(range.begin(), range.end());
}
if (v.is_unspecified())
return 0x4751301174351161ul;
return hash_value(v.to_string());
}
};
}
int main()
{
USER_MAP map;
map.insert({ {}, {} });
}
This is an old question, but I recently came across the same issue while writing a game in c++17.
This is how I solved it:
struct endpoint_hash
{
std::size_t operator()(boost::asio::ip::udp::endpoint const& ep) const noexcept
{
auto accum = std::size_t(0);
auto combine = [&accum](auto&& arg) {
boost::hash_combine(accum, arg);
};
combine(ep.port());
if (auto&& addr = ep.address(); addr.is_v4())
{
combine(addr.to_v4().to_ulong());
}
else
{
combine(addr.to_v6().to_bytes());
}
combine(ep.port());
return accum;
}
};
std::unordered_map<boost::asio::ip::udp::endpoint, std::shared_ptr<game_client>, endpoint_hash> cache_;
It will work if you write a hash function for IPaddress.

Unimplemented in new gcc but implemented in old one?

The code:
#include <tuple>
#include <cmath>
#include <iostream>
template <int N, typename Retrun_T, typename... Args_T>
Retrun_T _TupleFunctionCall(Retrun_T (*function)(Args_T... Args), std::tuple<Args_T...> Args, Args_T... RealArgs)
{
return function(RealArgs...);
}
template <int N, typename Retrun_T, typename... Args_T, typename... Interm_Args_T>
Retrun_T _TupleFunctionCall(Retrun_T (*function)(Args_T... Args), std::tuple<Args_T...> Args, Interm_Args_T... RealArgs)
{
return _TupleFunctionCall<N + 1>(function, Args, RealArgs..., std::get<N>(Args));
}
template <typename Retrun_T, typename... Args_T>
Retrun_T TupleFunctionCall(Retrun_T (*function)(Args_T... Args), std::tuple<Args_T...> Args)
{
return _TupleFunctionCall<1>(function, Args, std::get<0>(Args));
}
int main(int argc, char *argv[])
{
std::cout << TupleFunctionCall<double, double, double>(&std::pow, std::tuple<double, double>(10, 2)) << std::endl;
}
compiles and runs fine in g++ 4.4.2, but produces an error in g++ 4.5.2:
prog.cpp: In function 'Retrun_T _TupleFunctionCall(Retrun_T (*)(Args_T ...), std::tuple<_Tail ...>, Interm_Args_T ...) [with int N = 1, Retrun_T = double, Args_T = {double, double}, Interm_Args_T = {double}]':
prog.cpp:20:67: instantiated from 'Retrun_T TupleFunctionCall(Retrun_T (*)(Args_T ...), std::tuple<_Elements ...>) [with Retrun_T = double, Args_T = {double, double}]'
prog.cpp:25:104: instantiated from here
prog.cpp:14:84: sorry, unimplemented: use of 'type_pack_expansion' in template
prog.cpp:14:84: error: call of overloaded '_TupleFunctionCall(double (*&)(double, double), std::tuple&, double&, double&)' is ambiguous
prog.cpp:6:10: note: candidates are: Retrun_T _TupleFunctionCall(Retrun_T (*)(Args_T ...), std::tuple<_Tail ...>, Args_T ...) [with int N = 2, Retrun_T = double, Args_T = {double, double}]
prog.cpp:12:10: note: Retrun_T _TupleFunctionCall(Retrun_T (*)(Args_T ...), std::tuple<_Tail ...>, Interm_Args_T ...) [with int N = 2, Retrun_T = double, Args_T = {double, double}, Interm_Args_T = {double, double}]
Why is it implemented in old g++ but not in new one?
The question seems related to variadic template, you may refer to the link: GCC error with variadic templates: "Sorry, unimplemented: cannot expand 'Identifier...' into a fixed-length argument list"

Resources