Function of special template function - c++

I have a structure template e.g.:
template<typename KEY_T, typename VAL_T>
struct pair
{
KEY_T key; VAL_T val;
};
VAL_T val may be the different (string, list or smth else)
What I want is to overload the operator[] for the specified template structure pair<std::string, std::list>, and only for it.
How is it possible?
P.S. I'm writing an Ini-parser and I want to access for settings like settings[Section][Key], where settings[Section] returns the pair<std::string, std::list<Entry>> and settings[Section][Key] then return the string from std::list<Entry>

Class templates may be specialized, either partially:
template<typename T>
struct pair<std::string, std::list<T>>
{
std::string key;
std::list<T> val;
T& operator[](...) {
//implement
}
};
or fully:
template<>
struct pair<std::string, std::list<Entry>>
{
std::string key;
std::list<Entry> val;
Entry& operator[](...) {
//implement
}
};
As a side note, consider putting your classes in a designated namespace. Easier to manage if you ever need to work with std::pair too.

you can do this instead.
template <typename KEY, typename VAL>
struct pair
{
KEY _key;
VAL _val;
pair (const KEY& key, const VAL& val):
_key(key), _val(val)
{};
// ... here is the trick
friend ENTRY& get(pair<std::string, std::list<ENTRY>>& p, size_t idx)
};
ENTRY& get(pair<std::string, std::list<ENTRY>>& p, size_t idx)
{
return p._val [idx];
};
your question is not clear, you said:
Settings[Section] -> pair <string, list<entry>>;
Settings[Section][Key]-> list<entry>;?? the whole list object??
what you are looking for can be done like this:
std::map<std::string, std::map<std::string, std::string>> Settings;
std::string my_value = Settings[Section][Key];
Settings is a map of maps:
[Color] <-- this is the section
pen = blue <-- this is the pair KEY:VALUE
border = green
canvas = black

Related

Need a C++ map and list which contain iterators to each other

I have a custom templated container using a map and list being kept in sync. The map needs to hold MyList::const_iterator and the list needs to hold MyMap::const_iterator. The only solution I've been able to find is to pun one of the iterators, as in the example below.
Is there a proper way to forward declare this so that I don't need the ugly punning?
Runnable code available at http://coliru.stacked-crooked.com/a/a5eae03ad5090b27.
(There are definitely other approaches that could be used for the example, but that's out of scope. This is a snippet of a larger program. I'm simply trying to make this "circular" definition without UB.)
#include <iostream>
#include <list>
#include <unordered_map>
template<class ObjectT> class MyClass
{
private:
// SUMMARY: The map must contain an iterator to the list, and the list must contain an iterator to the map.
// I have not been able to figure out how to define that (circular), so I've punned an iterator to a different list for the map entry.
typedef std::list<ObjectT> PunnedList;
struct MapEntry
{
ObjectT m_object;
mutable typename PunnedList::const_iterator m_listIt; // Really a List::const_iterator, but that can't be defined.
};
typedef std::unordered_multimap<std::string, MapEntry> Map;
public:
struct ListEntry
{
typename Map::iterator m_mapIt;
const ObjectT& object() const
{
return m_mapIt->second.m_object;
}
const std::string& name() const
{
return m_mapIt->first;
}
};
private:
typedef std::list<ListEntry> List;
Map mMap;
List mList;
private:
typename List::const_iterator listiter_from_mapiter( typename Map::const_iterator& miter ) const
{
static_assert(sizeof(typename PunnedList::const_iterator) == sizeof(typename List::const_iterator));
return *(reinterpret_cast<typename List::const_iterator*>(&miter->second.m_listIt));
}
public:
typename List::const_iterator append( const std::string &name, const ObjectT& item )
{
static_assert(sizeof(typename PunnedList::const_iterator) == sizeof(typename List::const_iterator));
MapEntry entry{ item, typename PunnedList::const_iterator{} };
auto mapIter = mMap.insert({ name, entry });
mList.push_back({ mapIter });
auto iter = mList.cend();
--iter;
*(reinterpret_cast<typename List::const_iterator*>(&mapIter->second.m_listIt)) = iter;
return iter;
}
typename List::const_iterator begin() const
{
return mList.end();
}
typename List::const_iterator end() const
{
return mList.end();
}
void erase( typename List::const_iterator iter )
{
mMap.erase(iter->m_mapIt);
mList.erase( iter );
}
typename List::const_iterator find( const std::string &name ) const
{
auto range = mMap.equal_range(name);
for (auto mapIter = range.first; mapIter != range.second; ++mapIter)
{
// In the real program, there are additional criteria on the map entry, not needed for the example.
// if (mapIter is a match)
return listiter_from_mapiter(mapIter);
}
return mList.cend();
}
};
int main()
{
MyClass<int> container;
container.append("A",1);
container.append("B",2);
container.append("C",1);
std::cout << container.find("B")->object();
}
it's impossible to declare a type T that depend on a type Y which is also dependent on T. but you can use a wrapper to do that:
(it seems that you want to create a hash table in which elements are in insertion order? a common practice is to wrap the element and an iterator of a linked list.)
#include <string>
#include <list>
#include <unordered_map>
template<typename T>
class A{
struct Wrapper;
typedef std::unordered_multimap<std::string, Wrapper> Map;
typedef typename Map::const_iterator map_iter;
typedef std::list<map_iter> List;
typedef typename List::const_iterator list_iter;
struct Wrapper{
T value;
list_iter iter;
};
Map map;
List list;
public:
// do what you want
};
it works because to declare std::unordered_multimap<std::string, Wrapper>::iterator is not necessary to define Wrapper (needn't to be instantiated here).
Forward-declaring at least one of your inner classes breaks the cycle:
template<class ObjectT> class MyClass
{
public:
struct ListEntry;
private:
typedef std::list<ListEntry> List;
// Rest of the class, using List as you like
Note that the following List::const_iterator works thanks to std::list<T> not requiring T to be complete to be instantiated.

Adding methods with template specialization

I have a hash table container called Map with the following method:
Value Map<Key, Value>::valueFor(const Key& key);
Unfortunately, the most used case is for Key = std::string where we usually call the method with string literals such as:
const Value v = map.valueFor("my_key");
We loose a few cycles creating the std::string. Therefore, I would like to add an overload
Value Map<std::string, Value>::valueFor(const char* key);
when Key = std::string. I am sure that the compiler can even compute the hash at compile time with such a signature which would also help to speedup things.
Is there a way to do that in C++11 without template specializing the whole Map class and rewrite all the methods?
You can just add another overload valueFor(char const * key). Probably you then also want to disable this overload with SFINAE if the Key is not std::string.
#include <iostream>
#include <string>
#include <type_traits>
template < typename Key, typename Value >
struct Map
{
Value valueFor(Key const& key)
{
std::cout << "valueFor(const Key& key)\n";
return Value{};
}
template < typename _Key = Key,
typename = typename std::enable_if< std::is_same < _Key, std::string >::value >::type >
Value valueFor(char const * key)
{
std::cout << "valueFor(char const * key)\n";
return Value{};
}
};
int main()
{
Map<std::string, int> map;
int v = map.valueFor("my_key");
Map<int, int> other_map;
//int v = other_map.valueFor("my_key"); // BOOM!
}
Just weaken your type requirements. Your valueFor doesn't (need to) care what type the argument is, so long as the expression hash<Key>(arg) is valid.
So, you can template valueFor on its argument type, and just specialise your hash function and if necessary your key comparator.
eg. (untested, and using C++17 string_view for brevity)
template <typename K>
struct Hasher
{
static size_t hash(K const &k) { return std::hash<K>()(k); }
};
template <>
struct Hasher<std::string>
{
static size_t hash(std::string const &s) {
return std::hash<std::string>()(s);
}
static size_t hash(std::string_view const &sv) {
return std::hash<std::string_view>()(sv);
}
static size_t hash(const char *cstr) {
return std::hash<std::string_view>()({cstr});
}
};
template <typename Key, typename Value>
template <typename KeyArg>
Value Map<Key,Value>::valueFor(KeyArg&& arg)
{
auto hash = Hasher<Key>::hash(std::forward<KeyArg>(arg));
// ...
}

User-defined hash function for unordered_map

I am trying to create a templated wrapper class on stl unordered_map. I am passing the hash function class as a template parameter to the wrapper class and provided a string specialization. The below code compiles and works but if the commented part is included then compilation error saying:
"/usr/include/c++/6/bits/unordered_map.h:143:28: error: no matching
function for call to ‘HashFunction
::HashFunction()’
const hasher& __hf = hasher(),".
However, I am bound to have the ctor of the hash function class. I tried various ways but could not make it work. Please provide your thoughts/comments.
#include <iostream>
#include <unordered_map>
using namespace std;
template< class Key >
class HashFunction
{
public:
//HashFunction( const Key & inKey );
size_t operator()(const Key &inKey) const;
private:
unsigned mHashCode;
};
//template<>
//HashFunction< string >::HashFunction( const string & inKey )
//{
//mHashCode=std::hash<string>{}(inKey);
//}
template <>
size_t HashFunction< string >::operator()(const string &inKey) const
{
return std::hash<string>{}(inKey);
//return mHashCode;
}
template< class Key, class Val, class Hash = HashFunction< Key > >
class unordered_map_wrapper
{
public:
unordered_map_wrapper();
private:
unordered_map<Key, Val, Hash> * mTable;
};
template< class Key, class Val, class Hash >
unordered_map_wrapper< Key, Val, Hash >::unordered_map_wrapper()
{
mTable=new unordered_map<Key, Val, Hash>(10);
}
int main() {
unordered_map_wrapper<string, unsigned> h;
return 0;
}
This is not how the Hash template parameter is intended to work in std::unordered_map! The map creates one single Hash instance (using the default constructor, so you need to provide it!) which is used for all hash calculations needed further. So your class must look like this instead:
template<class Key>
class HashFunction
{
public:
// HashFunction(); <- can just leave it out...
size_t operator()(const Key& inKey) const;
};
template<>
size_t HashFunction<std::string>::operator()(const std::string& inKey) const
{
// calculate hash value in operator!!!
return std::hash<std::string>()(inKey);
}
To avoid constructing the std::hash all the time, though, I'd rather specialise the whole template class instead:
template<class Key>
class HashFunction; // leave entirely unimplemented
// (if it has no general meaning, at least...)
template<>
class HashFunction<std::string>
{
public:
size_t operator()(const std::string& inKey) const
{
return mHash(inKey);
}
private:
std::hash<std::string> mHash;
};
It does not make much sense re-implementing something that is already there, though. May I assume that you used std::string here just as a place holder for your own class?
By the way: A simple typedef would do the job easier than your wrapper class:
template <typename Key, typename Value>
using my_unordered_map = std::unordered_map<Key, Value, HashFunction<Key>>;
Maybe you are interested in alternatives, too? Lets first assume you have two classes (instead of std::string):
class C1
{ };
class C2
{ };
Most elegant solution (in my eyes at least) is simply specialising std::hash for your classes (while in general, it is illegal to add something to std namespace, template specialisations are the exception...):
namespace std
{
template<>
class hash<C1>
{
public:
size_t operator()(C const& c) const
{
return 0; // your implementation here...
}
};
// same for C2
}
// no typedef necessary, just use std::unordered_map directly:
std::unordered_map<C1, unsigned> m1;
std::unordered_map<C2, unsigned> m2;
You can provide your own HashFunction class, providing overloads:
class HashFunction
{
public:
size_t operator()(C1 const& c) const
{
return 0;
}
size_t operator()(C2 const& c) const
{
return 0;
}
};
Again, a typedef makes your life easier:
template <typename Key, typename Value>
using my_unordered_map = std::unordered_map<Key, Value, HashFunction>;
std::unordered_map<C1, unsigned, HashFunction> m1;
my_unordered_map<C1, unsigned> m1_;
std::unordered_map<C2, unsigned, HashFunction> m2;
my_unordered_map<C2, unsigned> m2_;
Finally, if you absolutely need to initialise your HashFunction with some parameters to configure it correctly, you can do so, but you have to deliver a pre-configured instance to your hash map then!
template<typename T>
class HashFunction
{
public:
HashFunction(double value);
size_t operator()(T const& c) const;
private:
double data;
};
template<typename T>
HashFunction<T>::HashFunction(double value)
: data(value)
{ }
template<>
size_t HashFunction<C1>::operator()(C1 const& c) const
{
return static_cast<size_t>(data);
};
template<>
size_t HashFunction<C2>::operator()(C2 const& c) const
{
return static_cast<size_t>(data);
};
template <typename Key, typename Value>
using my_unordered_map = std::unordered_map<Key, Value, HashFunction<Key>>;
my_unordered_map<C1, unsigned> m1(12, HashFunction<C1>(10.12));
my_unordered_map<C2, unsigned> m2(10, HashFunction<C2>(12.10));
Well, now, at least, your wrapper class can come in handy again:
template <typename Key, typename Value, typename Hash = HashFunction<Key>>
class unordered_map_wrapper
{
public:
unordered_map_wrapper()
: mMap(16, Hash())
{ }
unordered_map_wrapper(double parameter)
: mMap(16, Hash(parameter))
{ }
private:
std::unordered_map<Key, Value, Hash> mMap;
};
unordered_map_wrapper<C1, unsigned> m1(10.12);
unordered_map_wrapper<C2, unsigned> m2(12.10);
// possible due to provided default ctor:
unordered_map_wrapper<std::string, unsigned, std::hash<std::string>> m3;
It expects to have a default constructor, which is removed when you define your custom version.
This compiles:
template< class Key >
class HashFunction
{
public:
HashFunction(){};
HashFunction( const Key & inKey );
size_t operator()(const Key &inKey) const;
private:
unsigned mHashCode;
};

Template for traversing a tree node using boost::variant

Here is my design for traversal of a node tree:
struct Leaf1{};
struct Leaf2{};
struct Leaf3{};
struct Leaf4{};
struct Leaf5{};
typedef boost::variant< Leaf4, Leaf5 > Node3;
typedef boost::variant< Leaf2, Leaf3, Node3> Node2;
typedef boost::variant< Node2, Leaf1 > Node1;
class NodeVisitor: public boost::static_visitor<void>
{
public:
template<class Node>
void operator()(const Node& e) const
{
boost::apply_visitor( *this, e );
}
void operator()(const Leaf1& e) const{}
void operator()(const Leaf2& e) const{}
void operator()(const Leaf3& e) const{}
void operator()(const Leaf4& e) const{}
void operator()(const Leaf5& e) const{}
};
So I recursively visit the nodes until I arrive at a leaf. The problem above is that I must add a stub for operater() for each leaf. You can see that I have five such stubs above but have many more in practice. Can you suggest a way of templating this stub?
SOLUTION 1: SFINAE-based technique
This solution is based on the fact that failing to substitute template parameters during the instantiation of a template does not cause a compilation error (Substitution Failure Is Not An Error): instead, that template is simply disregarded for overload resolution. Thus, with some trick you can select which overloads of a certain function template shall be made visible depending on the template arguments provided at instantiation time.
When this technique is used, it is important to make sure that the discriminating conditions which decide the visibility of each overload are mutually exclusive, or ambiguity may arise.
To begin with, you need to define some trait metafunction that helps you determine whether a certain class is a leaf:
// Primary template
template<typename T> struct is_leaf<T> { static const bool value = false; };
// Specializations...
template<> struct is_leaf<Leaf1> { static const bool value = true; };
template<> struct is_leaf<Leaf2> { static const bool value = true; };
...
Then, you can use std::enable_if (or boost::enable_if if you are working with C++98) to select which overload of the call operator should be made visible:
class NodeVisitor: public boost::static_visitor<void>
{
public:
// Based on the fact that boost::variant<> defines a type list called
// "types", but any other way of detecting whether we are dealing with
// a variant is OK
template<typename Node>
typename std::enable_if<
!is_same<typename Node::types, void>::value
>::type
operator()(const Node& e) const
{
boost::apply_visitor( *this, e );
}
// Based on the fact that leaf classes define a static constant value
// called "isLeaf", but any other way of detecting whether we are dealing
// with a leaf is OK
template<typename Leaf>
typename std::enable_if<is_leaf<Leaf>::value>::type
operator()(const Leaf& e) const
{
...
}
};
SOLUTION 2: overload-based technique
If you are working on C++98 and do not want to use boost::enable_if as a replacement for std::enable_if, an alternative approach consists in exploiting overload resolution and an unused argument for discriminating between two overloads of a helper function. First of all, you define two dummy classes:
struct true_type { };
struct false_type { };
Then, you create your is_leaf<> metafunction again, properly specializing it for leaf classes:
// Primary template
template<typename T> struct is_leaf<T> { typedef false_type type; };
// Specializations...
template<> struct is_leaf<Leaf1> { typedef true_type type; };
template<> struct is_leaf<Leaf2> { typedef true_type type; };
...
Finally, you create an instance of one of those dummy types to choose the proper overload of a helper function process():
class NodeVisitor: public boost::static_visitor<void>
{
public:
template<typename T>
void operator()(const T& e) const
{
typedef typename is_leaf<T>::type helper;
process(e, helper());
}
template<typename Node>
void process(const Node& e, false_type) const
{
boost::apply_visitor(*this, e);
}
template<typename Leaf>
void process(const Leaf& e, true_type) const
{
...
}
};
Use an additional level of indirection for the LeafN class, something like:
template <typename LeafType>
struct LeafHolder
{
// has real instance of leaf..
};
Then redefine your variant type
typedef boost::variant< LeafHolder<Leaf4>, LeafHolder<Leaf5> > Node3;
typedef boost::variant< LeafHolder<Leaf2>, LeafHolder<Leaf3>, Node3> Node2;
typedef boost::variant< Node2, LeafHolder<Leaf1 > Node1;
Now your visitor can become:
class NodeVisitor: public boost::static_visitor<void>
{
public:
template<class Node>
void operator()(const Node& e) const
{
boost::apply_visitor( *this, e );
}
// single function to handle all leaves...
template <typename LeafType>
void operator()(const LeafHolder<LeafType>& e) const{}
};

Common code to iterate through different types of collections

Is there an elegant solution to use common code to iterate through hash_map/unordered_map and list/vector collections?
An example:
template<typename collection>
class multicast
{
public:
typedef collection collection_type;
private:
collection_type& m_channels;
public:
multicast(collection_type& channels) : m_channels(channels) { }
void operator ()(const buffer::ptr& head, const buffer::ptr& cnt)
{
for each(collection_type::value_type& ch in m_channels)
ch->send(head, cnt); /* this is where the magic should happen? */
}
}
This code obviously fails to compile when collection_type is unordered_map since collection_type::value_type is a pair so the code that access the actual value should be different: ch.second->send(head, cnt) instead of ch->send(head, cnt). So what would be the most elegant way to get rid of key part when it is not needed?
Yes:
for (auto & x : collection) { do_stuff_with(x); }
Alternatively:
for (auto it = std::begin(collection), end = std::end(collection); it != end; ++it)
{
do_stuff_with(*it);
}
If neither range-based for nor auto are available, you could write a template which takes a container C and use C::value_type and C::iterator; or you could make a template which accepts a pair of iterators of type Iter and uses std::iterator_traits<Iter>::value_type for the element value type.
Thirdly, you can use for_each and a lambda:
std::for_each(colllection.begin(), collection.end(),
[](collection::value_type & x) { do_stuff_with(x); });
To accommodate for both single-element and pair-element containers, you can build a little wrapper:
template <typename T> struct get_value_impl
{
typedef T value_type;
static value_type & get(T & t) { return t; }
};
template <typename K, typename V> struct get_value_impl<std::pair<K, V>>
{
typedef V value_type;
static value_type & get(std::pair<K,V> & p) { return p.second; }
};
template <typename T>
typename get_value_impl<T>::value_type & get_value(T & t)
{
return get_value_impl<T>::get(t);
}
Now you can use get_value(x) or get_value(*it) to get the value only.
The problem is that list/vector contains just a value, while map-s contains a pair of key-value. They are not the same thing, and to iterate the same way you shold at least define what part of the pair you are interested in.
Once defined, you essentially need a "derefence" operation that accepts an iterator, and -in case it has as a value_type a pair, return the second element, oterwise just dereference it.
// default case, returning itself
template<class T>
T& get_val(T& t) { return t; }
// case for pair (derefence for a map iterator)
template<class K, class V>
V& get_val(std::pair<const K, V>& s) { return s.second; }
// iterator dereference
template<class Iter>
decltype(get_val(*Iter()) deref_iter(const Iter& i)
{ return get_val(*i); }
Of course, const_iter version are also required, if needed.
Now:
for(auto i=container.begin(); i!=container-end(); ++i)
do_something_with(deref_iter(i));
will be the same whatever the container.