Unimplemented in new gcc but implemented in old one? - gcc

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"

Related

How to define a static constexpr matrix in c++14?

I am currently using C++14.
I would like to define a Matrix class which I can use for defining runtime matrices, but also constexpr matrices. I also would like to define static constexpr matrices based on such a class.
I consider this as a starting point for the Matrix class.
Then I would like to write something as:
static constexpr Matrix<double,2,2> staticmat{0.1,0.2,0.3,0.4};
so that staticmat is constexpr and unique, being static.
However, in order to initialise this, I would need a constexpr array or a constexpr initialiser list (not implemented in the link I posted, but not much would change). So I could write something like:
static constexpr std::array<double,4> staticmattmp{0.1,0.2,0.3,0.4};
static constexpr Matrix<double,2,2> staticmat(staticmattmp);
This would be ugly because I have to define two things just for one, but, if it worked, I could accept it. Unfortunately the compiler says unknown type name 'staticmattmp'.
How can I solve this, maybe in an elegant way?
How can I solve this, maybe in an elegant way?
I don't know if it's elegant but... with a little work...
First of all, define the following using
template <typename T, std::size_t>
using getType = T;
Next re-declare (declare only; not define) Matrix as follows
template <typename, std::size_t NR, std::size_t NC,
typename = std::make_index_sequence<NR*NC>>
class Matrix;
Now declare your Matrix as a class partial specialization adding a constructor that receive NR*NC elements of type T and use them to initialize the internal std::array
template <typename T, std::size_t NR, std::size_t NC, std::size_t ... Is>
class Matrix<T, NR, NC, std::index_sequence<Is...>>
{
public:
using value_type = T;
constexpr Matrix (getType<value_type, Is> ... vals)
: values_{{vals...}}
{}
// other member and methods
};
But don't forget to declare as default the destructor (maybe also constructor and operator=()).
The following is a full compiling C++14 example
#include <array>
#include <type_traits>
template <typename T, std::size_t>
using getType = T;
template <typename, std::size_t NR, std::size_t NC,
typename = std::make_index_sequence<NR*NC>>
class Matrix;
template <typename T, std::size_t NR, std::size_t NC, std::size_t ... Is>
class Matrix<T, NR, NC, std::index_sequence<Is...>>
{
public:
using value_type = T;
constexpr Matrix (getType<value_type, Is> ... vals)
: values_{{vals...}}
{}
constexpr Matrix (std::array<T, NR*NC> const & a)
: values_{a}
{}
constexpr Matrix (std::array<T, NR*NC> && a)
: values_{std::move(a)}
{}
constexpr Matrix () = default;
~Matrix() = default;
constexpr Matrix (Matrix const &) = default;
constexpr Matrix (Matrix &&) = default;
constexpr Matrix & operator= (Matrix const &) = default;
constexpr Matrix & operator= (Matrix &&) = default;
constexpr T const & operator() (std::size_t r, std::size_t c) const
{ return values_[r*NC+c]; }
T & operator() (std::size_t r, std::size_t c)
{ return values_[r*NC+c]; }
constexpr std::size_t rows () const
{ return NR; }
constexpr std::size_t columns () const
{ return NC; }
private:
std::array<T, NR*NC> values_{};
};
int main()
{
static constexpr Matrix<double,2,2> staticmat{0.1,0.2,0.3,0.4};
}

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.

Using C++ using: What am I doing wrong here?

The following code doesn't compile on the latest Microsoft Visual Studio. Could someone enlighten me on what I'm doing wrong here?
#include <iostream>
#include <iomanip>
#include <array>
template <typename T, std::size_t M, std::size_t N>
using Matrix = std::array<T, M * N>;
template <typename T, std::size_t M, std::size_t N>
std::ostream &operator<<(std::ostream &os, const Matrix<T, M, N> &matrix)
{
for (auto i = 0; i < M; ++i)
{
for (auto j = 0; j < N; ++j)
{
os << std::setw(5) << matrix[i * N + j];
}
os << std::endl;
}
return os;
}
int main(int argc, const char * const argv[])
{
Matrix<float, 2, 3> matrix{
1.1f, 1.2f, 1.3f,
2.1f, 2.2f, 2.3f
};
std::cout << matrix << std::endl;
return 0;
}
Here is a snapshot of the compiler error:
1>main.cpp(30): error C2679: binary '<<': no operator found which takes a right-hand operand of type 'std::array<T,6>' (or there is no acceptable conversion)
1> with
1> [
1> T=float
1> ]
Edit:
The following code works though:
#include <iostream>
#include <iomanip>
#include <array>
template <typename T, std::size_t M, std::size_t N>
using Matrix = std::array<std::array<T, N>, M>;
template <typename T, std::size_t M, std::size_t N>
std::ostream &operator<<(std::ostream &os, const Matrix<T, M, N> &matrix)
{
for (auto row : matrix)
{
for (auto element : row)
{
os << std::setw(5) << element;
}
os << std::endl;
}
return os;
}
int main(int argc, const char * const argv[])
{
Matrix<float, 2, 3> matrix{
1.1f, 1.2f, 1.3f,
2.1f, 2.2f, 2.3f
};
std::cout << matrix << std::endl;
return 0;
}
Bearing in mind #dyp's comment what you have to do here is to create the new type instead of alias that will have 2 independent params.
So you just use aggregation including actual data as a field, like:
template <typename T, std::size_t M, std::size_t N>
class Matrix
{
private:
std::array<T, M * N> _data;
template <typename T1, std::size_t M1, std::size_t N1> friend std::ostream &operator<<(std::ostream &os, const Matrix<T1, M1, N1> &matrix);
public:
template <typename...Args>
Matrix(Args... args):
_data{{std::forward<Args>(args)...}}
{}
};

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.

string literal parameter not accepted to a constexpr function

Call to the extract function below does not work for me on g++ 4.9.0 (20130421). The error I get is that s1 is not a constant expression. If i can be initialized as constexpr then j and k should too. Is that wrong?
#include <tuple>
template <unsigned N1, unsigned N2>
constexpr bool strmatch(const char (&s1)[N1], const char (&s2)[N2], unsigned i = 0)
{
return (s1[i]==s2[i]) ?
(s1[i]=='\0') ?
true
: strmatch(s1, s2, i+1)
: false;
}
template<unsigned N>
constexpr int extract(const std::tuple<int, int> & t1, const char (&array)[N]) {
return std::get<strmatch(array, "m0")>(t1);
}
int main(void)
{
constexpr int i = strmatch("m0", "m0"); // OK
constexpr int j = extract(std::make_tuple(10, 20), "m0");
constexpr int k = extract(std::make_tuple(10, 20), "m1");
return 0;
}
Your code is ill-formed. The problem is that array is not a core constant expression, so can't be used in the template argument in the call to std::get:
template<unsigned N>
constexpr int extract(const std::tuple<int, int> & t1, const char (&array)[N]) {
return std::get<strmatch(array, "m0")>(t1);
}
Remember that constexpr functions can be called at runtime: this code would use the value of a runtime parameter to this function (array) during translation (in the evaluation of the call to strmatch).

Resources