how to create a hash function which can be parametrized? - c++

I want to create a hash function that is supported by template types T and E.
I use:
namespace std {
namespace tr1 {
template<class T, class E> struct hash<my_class<T, E> >
{
public:
size_t operator()(const my_class<T, E>& k) const
{
return ((hash<T>()(k.a()))^ (hash<E>()(k.x()) << 1) >> 1);
}
};
}
}
but I get errors such as:
In file included from g.cpp:1:
g.h:35: error: ‘hash’ is not a template
g.h:36: error: explicit specialization of non-template ‘hash’
g.h:76: error: ‘hash’ is not a template
g.h:76: error: ‘hash’ is not a template type
Is there no way to specialize a hash function so that it can use a template?
If not, how would I construct a hash function which is based on generic types T and E?
EDIT: Someone answered below, but not quite to my question. I am interested in being able to define a hash function which itself uses generic types. Something like hash< some_class < T > > where T is a generic type.

hash is in namespace std not in namespace std::tr1. See the snippet from en.cppreference.com for an example on how to specialize it (of course you can also partial specialize it):
#include <iostream>
#include <functional>
#include <string>
struct S
{
std::string first_name;
std::string last_name;
};
namespace std
{
template<>
struct hash<S>
{
typedef S argument_type;
typedef std::size_t value_type;
value_type operator()(argument_type const& s) const
{
value_type const h1 ( std::hash<std::string>()(s.first_name) );
value_type const h2 ( std::hash<std::string>()(s.last_name) );
return h1 ^ (h2 << 1);
}
};
}
int main()
{
S s;
s.first_name = "Bender";
s.last_name = "Rodriguez";
std::hash<S> hash_fn;
std::cout << "hash(s) = " << hash_fn(s) << "\n";
}

It's not a good idea to pollute any standard namespace with your own functions. Just put the class in your own namespace and you can do whatever you want. In your case, just make your own class API-compatible with the standard hash. Additionally, there's no problem in calling the standard hash from within your own hash.

Related

Static member definition of complex type of a template class with SFINAE

It is fairly standard way to declare and define a static const member of a complex type of a template class. However, I would to use SFINAE patter in my class. And that leads to this error: template definition of non-template 'const std::array<unsigned int, 2ul> Message<Self>::kData'. Removing SFINAE resolves the error.
Here is the code:
#include <iostream>
#include <type_traits>
#include <array>
using namespace std;
template <class Self, typename = std::enable_if_t<std::is_class<Self>::value>>
class Message
{
public:
bool Verify() const { return static_cast<const Self *>(this)->Verify(); }
static const std::array<uint32_t, 2> kData;
};
class Command : public Message<Command>
{
public:
bool Verify() {
std::cout << "Command::Verify";
return true;
}
};
template <class Self, typename = std::enable_if_t<std::is_class<Self>::value>>
const std::array<uint32_t, 2> Message<Self>::kData = { 12, 13 };
int main()
{
Command cmd;
cout << "Data: " << cmd.kData[0] << endl;
return 0;
}
Live code is here.
What is the proper syntax to still use SFINAE and properly define the static constant?
What is the proper syntax to still use SFINAE and properly define the static constant?
Simply using a generic type T
// ............................V
template <class Self, typename T>
const std::array<uint32_t, 2> Message<Self, T>::kData = { 12, 13 };
// .......................................^^^
Template default types/values aren't used in external definitions.

error: 'hash' is not a class template

#include <unordered_map>
#include <memory>
#include <vector>
template<> // Voxel has voxel.position which is a IVec2 containing 2 values, it also has a bool value
struct hash<Voxel> {
size_t operator()(const Voxel & k) const
{
return Math::hashFunc(k.position);
}
};
template<typename T> // This was already given
inline size_t hashFunc(const Vector<T, 2>& _key)
{
std::hash<T> hashfunc;
size_t h = 0xbd73a0fb;
h += hashfunc(_key[0]) * 0xf445f0a9;
h += hashfunc(_key[1]) * 0x5c23b2e1;
return h;
}
My main
int main()
{
Voxel t{ 16,0,true };
std::hash(t);
}
Right now i am writing on an specialisation for std::hash. Now the online submission page always returns the following errors for my code. I don't know why and what i did wrong.
error: 'hash' is not a class template struct hash<>
and
error: no match for call to '(const std::hash<Math::Vector<int, 2ul> >) (const Math::Vector<int, 2ul>&)' noexcept(declval<const_Hash((declval<const_Key&>()))>.
My own compiler only throws
error: The argument list for "class template" std :: hash "" is missing.
For posterity, I got the same error message when I had forgotten to #include <functional>.
You are specializing std::hash<> in the global namespace and this is ill-formed.
The specialization must be declared in the same namespace, std. See the example for std::hash:
// custom specialization of std::hash can be injected in namespace std
namespace std
{
template<> struct hash<S>
{
typedef S argument_type;
typedef std::size_t result_type;
result_type operator()(argument_type const& s) const
...

Boost fusion using transform in for_each

I'm trying to build a small C++ example using boost fusion. However, Visual Studio 2013 gives me build errors for the following piece of code. It should simply go over a associative struct and print all member names to the console:
#include <iostream>
#include <type_traits>
#include <boost/fusion/adapted/struct/define_assoc_struct.hpp>
#include <boost/fusion/algorithm/iteration/for_each.hpp>
#include <boost/fusion/algorithm/transformation/zip.hpp>
#include <boost/fusion/algorithm/transformation/transform.hpp>
namespace keys
{
struct name
{};
struct id
{};
}
BOOST_FUSION_DEFINE_ASSOC_STRUCT((), Student,
(std::string, name, keys::name)
(int, id, keys::id)
);
struct getnames
{
template<typename Sig>
struct result;
template <typename S, typename T>
struct result<getnames(S, T)>
{
typedef std::string type;
};
template<class Struct, class N>
typename result<getnames(Struct, N)>::type operator() (const N& i) const
{
return boost::fusion::extension::struct_member_name<Struct, i>::call();
}
};
struct print
{
template<typename Sig>
struct result;
template <typename T>
struct result<print(T)>
{
typedef void type;
};
template<class S>
void operator() (const S& i) const
{
std::cout << i << std::endl;
};
};
int main()
{
Student j = {"John", 42};
auto names = boost::fusion::transform(j, getnames());
boost::fusion::for_each(names, print());
return 0;
}
This is my error:
boost/fusion/view/transform_view/detail/deref_impl.hpp(38): error C2039: 'type' : is not a member of 'boost::mpl::apply<boost::fusion::detail::apply_transform_result<getnames>,const std::basic_string<char,std::char_traits<char>,std::allocator<char>> &,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na>'
and four more errors which are coming up because of the first one.
To be honest, I am not an expert in the usage of boost fusion so maybe I simply missed something important here and someone else can help me.
There are several problems with your code.
1) In the Functor getnames, the signature of the result type and the signature of operator() are inconsistent (one takes one argument, the other takes two).
2) in the operator()(const N& i), i is a runtime variable. It cannot appear as a template parameter in the expression boost::fusion::extension::struct_member_name<Struct, i>.
I am not sure how to help without knowing what you want to do with getnames. Try to get to a consistent code first.

Deducing the return type of a map with varying value types

I have the following code
#include <boost\any.hpp>
#include <iostream>
#include <memory>
#include <map>
#include <string>
enum class tags { int_param, string_param };
class Parameters
{
public:
template <typename T>
void set(tags key, T value)
{
map_[key] = value;
}
template <typename T>
T get(tags key)
{
return boost::any_cast<T>(map_[key]);
}
private:
std::map<tags, boost::any> map_;
};
int main()
{
Parameters params;
params.set(tags::int_param, 42);
params.set(tags::string_param, "it works!");
int int_par = params.get<int>(tags::int_param);
std::string string_par = params.get<std::string>(tags::string_param);
std::cout << "Channel: " << int_par << std::endl;
std::cout << "Filename: " << string_par << std::endl;
}
This code works however I do not like having to supply the templated type and I would like, if at all possible, to be able to retrieve something from the map without having to supply the template type i.e.
int int_par = params.get(tags::int_param);
instead of
int int_par = params.get<int>(tags::int_param);
I understand by using boost::any that we need to cast to a supplied type from the any type but is there a way we can do it without having to supply it ourself and can we instead deduce it some other way>
If you change tags from enum values to structs you can achieve the desired behavior and even other good features, such as type safety and that our use of any_cast won't ever throw.
By using structs we can define simple traits to get each tags value type, such as
enum class tag_id
{
int_param; // Id which represents int_param tag on std::map
}
struct int_param_t
{
using value_type = int;
static const tag_id id;
};
const tag_id int_param_t::id = tag_id::int_param;
Now we can use this traits to achieve your desired syntax
template< typename Tag >
auto get( Tag ) -> typename Tag::valye_type
{
return boost::any_cast<typename Tag::valye_type>(map_[Tag::id]);
}
// ...
int a = parameters.get( int_param_t{} ); // Ok, returns int.
std::string b = parameters.get( int_param_t{} ); // Error, int is not convertible to std::string.
As a bonus we can use this traits to ensure only types convertable to the correct type are used with set function
template< typename Tag >
void set( Tag, typename Tag::value_type value )
{
map_[Tag::id] = value;
}
// ...
parameter.set( int_param_t{}, 0 ); // Ok, 0 is convertible to int.
parameter.set( int_param_t{}, "string" ); // Error, const char[] is not convertible to int.
To make it a little bit prettier, I would also define some alias and constants such as
// Helper alias to avoid writing typename everywhere.
template< typename T >
using param_type = typename T::value_type;
// Used to avoid having to create tag objects every function call.
constexpr int_param_t int_param{};
And here is the final product
#include <boost/any.hpp>
#include <iostream>
#include <memory>
#include <map>
#include <string>
namespace tags
{
enum class tag_id
{
int_param,
string_param
};
struct int_param_t
{
using value_type = int;
static const tag_id id;
};
const tag_id int_param_t::id = tag_id::int_param;
constexpr int_param_t int_param{};
struct string_param_t
{
using value_type = std::string;
static const tag_id id;
};
const tag_id string_param_t::id = tag_id::string_param;
constexpr string_param_t string_param{};
}
// Helper alias to avoid writing typename everywhere.
template< typename T >
using param_type = typename T::value_type;
class Parameters
{
public:
template <typename Tag>
void set(Tag, param_type< Tag > value)
{
map_[Tag::id] = value;
}
template <typename Tag>
auto get(Tag) -> param_type< Tag >
{
return boost::any_cast< param_type< Tag > >(map_[Tag::id]);
}
private:
std::map<tags::tag_id, boost::any> map_;
};
int main()
{
Parameters params;
params.set(tags::int_param, 42);
params.set(tags::string_param, "it works!");
int int_par = params.get(tags::int_param);
std::string string_par = params.get(tags::string_param);
std::cout << "Channel: " << int_par << std::endl;
std::cout << "Filename: " << string_par << std::endl;
}
There is no way to deduce anything from an any but there might be a chance to deduce something from the declaration. As your code already throws when any_cast fails, I suppose this is not an issue for you.
You could extend (really a bad idea to due to the missing virtual destructor) boost::any or wrap it and provide a templated conversion operator.
#include <boost/any.hpp>
#include <iostream>
struct converting_any {
converting_any(boost::any* a) : a(a) {}
template<typename T>
operator T() { return boost::any_cast<T>(*a); } // dereference to get the throwing version
private:
boost::any* a; // wrapped any
};
int main()
{
int i = 3; std::string j = "asddf";
boost::any a = i;
int i2 = converting_any(&a);
try {
std::string j2 = converting_any(&a);
} catch(...) {
std::cout << "Failure." << std::endl;
}
a = j;
std::string j3 = converting_any(&a);
return 0;
}
You could return a reference wrapper which postpones the cast until its needed:
struct converter {
converter(boost::any & any) : any(any) {}
template <typename T>
operator T() {return boost::any_cast<T>(any);}
boost::any & any;
};
converter get(tags key)
{
return map_[key];
}
The template argument can be deduced from the type being converted to, so your int example will work without an explicit template argument.
Note that, as with your version, this will fail if the template parameter doesn't match the variant's type, as demonstrated in your example when attempting to convert const char * to std::string.

Translating a std::tuple into a template parameter pack

I have a
typedef std::tuple<A, B> TupleType;
and would like to use the list of classes
for a "template".
Suppose I have:
template<typename... args>
std::tuple<args...> parse(std::istream &stream) {
return std::make_tuple(args(stream)...);
}
and that I can successfully use it with:
auto my_tuple = parse<A, B>(ifs);
is it possible to avoid having to specify the class list A,B if I already have a
typedef std::tuple<A,B> TupleType;
where the list A,B is already present?
an example:
#include <cstdlib> // EXIT_SUCCESS, EXIT_FAILURE
#include <iostream> // std::cerr
#include <fstream> // std::ifstream
#include <tuple> // std::tuple
class A {
public:
A(std::istream &); // May throw FooBaarException
};
class B {
public:
B(std::istream &); // May throw FooBaarException
};
template<typename... args>
std::tuple<args...> parse(std::istream &stream) {
return std::make_tuple(args(stream)...);
}
int main() {
std::ifstream ifs;
ifs.exceptions(ifstream::eofbit | ifstream::failbit | ifstream::badbit);
int res = EXIT_FAILURE;
try {
ifs.open("/some/file/path", std::ios::in | std::ios::binary);
auto my_tuple = parse<A, B>(ifs); // my_tuple is of the type std::tuple<A,B>
/* Here do something interesting with my_tuple */
res = EXIT_SUCCESS;
} catch (ifstream::failure e) {
std::cerr << "error: opening or reading file failed\n";
} catch (FooBaarException e) {
std::cerr << "error: parsing in a constructor failed\n";
}
return res;
}
The underlying problem in your situation seems to be that you'd like to specialize the function template parse for the special case when the template argument is a std::tuple. Unfortunately, this kind of specialization isn't possible with function templates.
However, it is possible with class templates.
So, as a first step, you could define parse as a static function of a struct, like this:
using std::istream;
using std::tuple;
using std::make_tuple;
struct A { A(const istream &) {} };
struct B { B(const istream &) {} };
template <typename... Args>
struct parser
{
/* Your original function, now inside a struct.
I'm using direct tuple construction and an
initializer list to circumvent the order-of-
construction problem mentioned in the comment
to your question. */
static tuple<Args...> parse(const istream &strm)
{ return tuple<Args...> {Args(strm)...}; }
};
template <typename... Args>
struct parser<tuple<Args...>>
{
/* Specialized for tuple. */
static tuple<Args...> parse(const istream &strm)
{ return parser<Args...>::parse(strm); }
};
You can then call it in the desired way:
int main()
{
typedef tuple<A,B> tuple_type;
auto tup = parser<tuple_type>::parse(std::cin);
return 0;
}
As a second step, you can define a function template (again) which passes the arguments on to the right specialization of the struct:
template <typename... Args>
auto parse(const istream &strm) -> decltype(parser<Args...>::parse(strm))
{ return parser<Args...>::parse(strm); }
And now you can use it in exactly the way you wanted:
int main()
{
typedef tuple<A,B> tuple_type;
auto tup = parse<tuple_type>(std::cin);
return 0;
}
(And you can still use it in the old way, too: auto tup = parse<A,B>(std::cin).)
Remark. As mentioned in the comment to parser::parse(), I used direct tuple construction instead of make_tuple to avoid problems with the order of construction of the tuple elements. This is not directly related to your question, but a good thing to do. See how to avoid undefined execution order for the constructors when using std::make_tuple.
There is a standard idiom for this kind of thing. [1]
// Define the "shape" of the template
template<typename Tuple> struct TupleMap;
// Specialize it for std::tuple
template<typename...T> struct TupleMap<std::tuple<T...>> {
using type = std::tuple<T...>; // not necessary but saves typing
// ... inside here, you have access to the parameter pac
}
Here's an example of using it, which might or might not fit your expectations (your example doesn't really indicate your expected use, since it lacks the typedef you promise in your question): liveworkspace.org.
Since litb raised the point, it is possible to force the tuple-components to be constructed in left-to-right order, illustrating another interesting idiom: comb inheritance. See lws.
(Since lws might disappear again, who knows, I'll paste the code here as well):
#include <iostream>
#include <tuple>
#include <type_traits>
#include <utility>
// Define the "shape" of the template
template<typename Tuple> struct TupleMap;
// Specialize it for std::tuple
template<typename...T> struct TupleMap<std::tuple<T...>> {
using type = std::tuple<T...>; // not necessary but saves typing
type value;
template<typename Arg>
TupleMap(Arg&& arg)
: value(T(std::forward<Arg>(arg))...) {
}
operator type() { return value; }
};
//Try it out:
using std::get; // Note 2
using Numbers = std::tuple<char, double, int>;
// Note 3
std::ostream& operator<<(std::ostream& out, const Numbers& n) {
return out << get<0>(n) << ' ' << get<1>(n) << ' ' << get<2>(n);
}
int main() {
std::cout << TupleMap<Numbers>(93.14159);
return 0;
}
[1] At least, I think it's a standard idiom. I use it a lot, and think of it as the "can-opener" pattern.
[2] This is needed (or at least, it's my style) to allow the use of get with tuple-like templates defined outside of std. Doing it this way allows ADL to find the appropriate definition of get without forcing me to add specializations to std::get. In this way, it's similar to the standard ADL idiom for begin and end.
[3] You can search SO for a cool hack to specialize operator<< for all tuples. There's a simpler one which can be used for specific tuples, but that's all off-topic for this question, so I just did something easy and dependency free. Note that this works because of the conversion operator in TupleMap
The basic approach is to create a sequence of indices 0, ..., std::tuple_size<Tuple>::value - 1 as a parameter pack Indices and call your function with parse<typename std::tuple_element<Tuple, Indices>::type...>(stream). You'd probably encapsulate the logic into a function parse_tuple<Tuple>(stream) (and some function this one delegates to) which in the end delegates to parse<...>(stream).
First, here is a class template and a function to create a sequence of indices based on the size of a std::tuple. The indices are needed to obtain a list of type from std::tuple:
template <int... Indices> struct indices;
template <>
struct indices<-1> { // for an empty std::tuple<> there is no entry
typedef indices<> type;
};
template <int... Indices>
struct indices<0, Indices...> { // stop the recursion when 0 is reached
typedef indices<0, Indices...> type;
};
template <int Index, int... Indices>
struct indices<Index, Indices...> { // recursively build a sequence of indices
typedef typename indices<Index - 1, Index, Indices...>::type type;
};
template <typename T>
typename indices<std::tuple_size<T>::value - 1>::type const*
make_indices() {
return 0;
}
With this in place, it is quite easy to extract the sequence of types from a std::tuple<T...>:
template<typename T, int... Indices>
T parse_tuple(std::istream &stream, indices<Indices...> const*) {
return parse<typename std::tuple_element<Indices, T>::type...>(stream);
}
template <typename T>
T parse_tuple(std::istream& stream) {
return parse_tuple<T>(stream, make_indices<T>());
}