Vector of vectors of T in template<T> class - c++

Why this code does not compile (Cygwin)?
#include <vector>
template <class Ttile>
class Tilemap
{
typedef std::vector< Ttile > TtileRow;
typedef std::vector< TtileRow > TtileMap;
typedef TtileMap::iterator TtileMapIterator; // error here
};
error: type std::vector<std::vector<Ttile, std::allocator<_CharT> >, std::allocator<std::vector<Ttile, std::allocator<_CharT> > > >' is not derived from typeTilemap'

Because the TtileMap::iterator is not known to be a type yet. Add the typename keyword to fix it
typedef typename TtileMap::iterator TtileMapIterator;

Related

Error when template parameter passed to boost multi index container

I am trying to use multi_index_container with templates. below is my code.
template < class ValueType >
class anrQueue
{
private:
typedef boost::multi_index_container<
ValueType,
indexed_by<
sequenced<>,
ordered_unique<identity<ValueType> >
>
> a_queue;
a_queue mQueue;
public:
size_t remove(const ValueType& x) {
return mQueue.get<1>().erase(x);
}
-------------------------^
error: expected primary-expression before ‘)’ token
How to resolve this
Write:
return mQueue.template get<1>().erase(x);
Look here for an explanation on the usage of template on dependent contexts.

Inner scoped enumeration, hash function and unordered_set data member

I've the following problem of which I cannot find a solution.
Of course, it could be that a solution does not exist at all, but I'd like to have a try on SO before to give up.
First of all, a snippet that compiles with no errors:
#include <unordered_set>
#include <memory>
struct S {
enum class E: unsigned int { FOO = 0, BAR };
};
namespace std
{
template<>
struct hash<S::E> {
using argument_type = S::E;
using underlying_type = std::underlying_type<argument_type>::type;
using result_type = std::size_t;
result_type operator()(argument_type const &s) const noexcept {
const underlying_type us = static_cast<underlying_type>(s);
hash<underlying_type> hfn;
return hfn(us);
}
};
}
int main() {
std::unordered_set<S::E> set;
}
With this code in mind, I found myself with the requirement of having the unordered_set as a data member of S or, at least, a derived class. A possible working solution is to add add the following lines once the std namespace has been closed:
struct D: public S {
std::unordered_set<S::E> set;
};
Another possible solution is maybe (I've not tried it) to use an unscoped enumeration. Anyway, the first attempt I made was to modify the definition of the struct S as it follows:
struct S {
enum class E: unsigned int { FOO = 0, BAR };
std::unordered_set<E> set;
};
This ends in an error because (if I've correctly understood the problem) the unordered_set requires the specialized hash function. Anyway, the latter requires S::E to be at least declared, thus it is not enough to swap the two pieces of code.
Here the first part of the error log (for it's very long):
In file included from /usr/include/c++/5/bits/hashtable.h:35:0,
from /usr/include/c++/5/unordered_set:47,
from main.cpp:1:
/usr/include/c++/5/bits/hashtable_policy.h: In instantiation of ‘struct std::__detail::__is_noexcept_hash<S::E, std::hash<S::E> >’:
/usr/include/c++/5/type_traits:137:12: required from ‘struct std::__and_<std::__is_fast_hash<std::hash<S::E> >, std::__detail::__is_noexcept_hash<S::E, std::hash<S::E> > >’
/usr/include/c++/5/type_traits:148:38: required from ‘struct std::__not_<std::__and_<std::__is_fast_hash<std::hash<S::E> >, std::__detail::__is_noexcept_hash<S::E, std::hash<S::E> > > >’
/usr/include/c++/5/bits/unordered_set.h:95:63: required from ‘class std::unordered_set<S::E>’
main.cpp:6:27: required from here
/usr/include/c++/5/bits/hashtable_policy.h:85:34: error: no match for call to ‘(const std::hash<S::E>) (const S::E&)’
noexcept(declval<const _Hash&>()(declval<const _Key&>()))>
^
In file included from /usr/include/c++/5/bits/move.h:57:0,
from /usr/include/c++/5/bits/stl_pair.h:59,
from /usr/include/c++/5/utility:70,
from /usr/include/c++/5/unordered_set:38,
from main.cpp:1:
/usr/include/c++/5/type_traits: In instantiation of ‘struct std::__not_<std::__and_<std::__is_fast_hash<std::hash<S::E> >, std::__detail::__is_noexcept_hash<S::E, std::hash<S::E> > > >’:
/usr/include/c++/5/bits/unordered_set.h:95:63: required from ‘class std::unordered_set<S::E>’
main.cpp:6:27: required from here
/usr/include/c++/5/type_traits:148:38: error: ‘value’ is not a member of ‘std::__and_<std::__is_fast_hash<std::hash<S::E> >, std::__detail::__is_noexcept_hash<S::E, std::hash<S::E> > >’
: public integral_constant<bool, !_Pp::value>
^
In file included from /usr/include/c++/5/unordered_set:48:0,
from main.cpp:1:
/usr/include/c++/5/bits/unordered_set.h: In instantiation of ‘class std::unordered_set<S::E>’:
main.cpp:6:27: required from here
/usr/include/c++/5/bits/unordered_set.h:95:63: error: ‘value’ is not a member of ‘std::__not_<std::__and_<std::__is_fast_hash<std::hash<S::E> >, std::__detail::__is_noexcept_hash<S::E, std::hash<S::E> > > >’
typedef __uset_hashtable<_Value, _Hash, _Pred, _Alloc> _Hashtable;
^
/usr/include/c++/5/bits/unordered_set.h:102:45: error: ‘value’ is not a member of ‘std::__not_<std::__and_<std::__is_fast_hash<std::hash<S::E> >, std::__detail::__is_noexcept_hash<S::E, std::hash<S::E> > > >’
typedef typename _Hashtable::key_type key_type;
Usually, in such a case, I can solve with something like a forward declaration, as the one in the example below:
struct B;
struct A { B *link; };
struct B { A *link; };
Unfortunately, I've not been able to do something similar with the enum embedded in a struct and that's why I started this question. Is it possible to solve it, thus avoid to define the derived class D, or deriving is the only viable solution in this case?
You can't forward declare a nested enum, see this answer.
You can do as ForEveR explained, or you can have your generic enum_hash template regardless of std namespace and use it in your data structure, since you are not forced to use std::hash as the hashing function, eg:
template<typename T>
struct enum_hash {
using argument_type = T;
using underlying_type = typename std::underlying_type<argument_type>::type;
using result_type = std::size_t;
result_type operator()(argument_type const &s) const noexcept {
const underlying_type us = static_cast<underlying_type>(s);
std::hash<underlying_type> hfn;
return hfn(us);
}
static_assert(std::is_enum<T>::value, "T must be an enum!");
};
struct S {
enum class E: unsigned int { FOO = 0, BAR };
std::unordered_set<S::E, enum_hash<S::E>> set;
};
You can just write specialization of hash for all enums and then all would work fine.
namespace std {
template<class E>class hash {
using sfinae = typename std::enable_if<std::is_enum<E>::value, E>::type;
public:
size_t operator()(const E&e) const {
return std::hash<typename std::underlying_type<E>::type>()(e);
}
};
};

error for hash function of pair of ints

I have the following class with an unordered_map member, and a hash function defined for pair<int,int>
class abc
{public :
unordered_map < pair<int,int> , int > rules ;
unsigned nodes;
unsigned packet ;
};
namespace std {
template <>
class hash < std::pair< int,int> >{
public :
size_t operator()(const pair< int, int> &x ) const
{
size_t h = std::hash<int>()(x.first) ^ std::hash<int>()(x.second);
return h ;
}
};
}
But I am getting the following errors :
error: invalid use of incomplete type ‘struct std::hash<std::pair<int, int> >
error: declaration of ‘struct std::hash<std::pair<int, int> >
error: type ‘std::__detail::_Hashtable_ebo_helper<1, std::hash<std::pair<int, int> >, true>’ is not a direct base of ‘std::__detail::_Hash_code_base<std::pair<int, int>, std::pair<const std::pair<int, int>, int>, std::__detail::_Select1st, std::hash<std::pair<int, int> >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, true>’
Unfortunately, this program has undefined behavior. C++11 §17.6.4.2.1:
A program may add a template specialization for any standard library template to namespace std only if the declaration depends on a user-defined type and the specialization meets the standard library requirements for the original template and is not explicitly prohibited.
hash<pair<int,int>> depends on primitive and standard library types only. This is easily worked around by defining your hash class outside of namespace std, and using that hash explicitly in your map declaration:
struct pairhash {
public:
template <typename T, typename U>
std::size_t operator()(const std::pair<T, U> &x) const
{
return std::hash<T>()(x.first) ^ std::hash<U>()(x.second);
}
};
class abc {
std::unordered_map<std::pair<int,int>, int, pairhash> rules;
};
EDIT: I've used xor to combine the hashes of the pair members here because I'm lazy, but for serious use xor is a fairly crappy hash combining function.
I prefer to rely on the standard implementation of std::hash<uintmax_t> to mix hashes of components of an std::pair:
#include <functional>
#include <utility>
struct hash_pair final {
template<class TFirst, class TSecond>
size_t operator()(const std::pair<TFirst, TSecond>& p) const noexcept {
uintmax_t hash = std::hash<TFirst>{}(p.first);
hash <<= sizeof(uintmax_t) * 4;
hash ^= std::hash<TSecond>{}(p.second);
return std::hash<uintmax_t>{}(hash);
}
};

Custom allocator & default member

Why isn't this code compiling ?
#include <cstdlib>
#include <list>
template < typename Type >
class Allocator {
public:
using value_type = Type;
public:
template < typename Other >
struct rebind { using other = Allocator< Other >; };
public:
Type * allocate( std::size_t n ) { return std::malloc( n ); }
void deallocate( Type * p, std::size_t ) throw ( ) { std::free( p ); }
};
int main( void ) {
std::list< void *, Allocator< void * > > list;
return 0;
}
It seems to need pointer, reference, pointer_const & reference_const types. However, according to cppreference these members are all optionals. It seems like if the STL weren't using allocator_trait (I'm compiling with -std=c++11 so it should be good).
Any idea ?
[edit] On clang, errors are :
user#/tmp > clang++ -std=c++11 test.cc
In file included from test.cc:2:
In file included from /usr/lib/gcc/i686-pc-linux-gnu/4.7.1/../../../../include/c++/4.7.1/list:63:
/usr/lib/gcc/i686-pc-linux-gnu/4.7.1/../../../../include/c++/4.7.1/bits/stl_list.h:449:40: error: no type named 'pointer' in 'Allocator<void *>'
typedef typename _Tp_alloc_type::pointer pointer;
~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
test.cc:17:46: note: in instantiation of template class 'std::list<void *, Allocator<void *> >' requested here
std::list< void *, Allocator< void * > > list;
^
In file included from test.cc:2:
In file included from /usr/lib/gcc/i686-pc-linux-gnu/4.7.1/../../../../include/c++/4.7.1/list:63:
/usr/lib/gcc/i686-pc-linux-gnu/4.7.1/../../../../include/c++/4.7.1/bits/stl_list.h:450:40: error: no type named 'const_pointer' in 'Allocator<void *>'
typedef typename _Tp_alloc_type::const_pointer const_pointer;
~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~
/usr/lib/gcc/i686-pc-linux-gnu/4.7.1/../../../../include/c++/4.7.1/bits/stl_list.h:451:40: error: no type named 'reference' in 'Allocator<void *>'
typedef typename _Tp_alloc_type::reference reference;
~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~
/usr/lib/gcc/i686-pc-linux-gnu/4.7.1/../../../../include/c++/4.7.1/bits/stl_list.h:452:40: error: no type named 'const_reference' in 'Allocator<void *>'
typedef typename _Tp_alloc_type::const_reference const_reference;
~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~
4 errors generated.
This is a bug in GCC's C++ standard library.
When using a list, they are not properly wrapping access to the allocator through an allocator_traits.
However, they do implement vector correctly. This code would compile if you used std::vector instead of std::list.

Parsing a structure in an associative manner with Boost Spirit and Fusion

I'm trying to parse a key-value string into a structure. Some key-values may be absent or may be in different order, so I wanted to use boost::fusion to adapt the structure and then parse into it with at_key<> directive.
#include <iostream>
#include <string>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/fusion/adapted.hpp>
#include <boost/fusion/sequence.hpp>
using namespace std;
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
namespace phx = boost::phoenix;
using boost::fusion::at_key;
typedef string::const_iterator iter_type;
struct Couple {
int a;
int b;
Couple() : a(0), b(0) {}
};
namespace keys {
struct first;
struct second;
}
BOOST_FUSION_ADAPT_ASSOC_STRUCT(
Couple,
(int, a, keys::first)
(int, b, keys::second)
)
struct G: qi::grammar< iter_type, Couple(), ascii::space_type >
{
G() : G::base_type( start_rule ) {
using qi::_val;
using qi::_1;
using qi::_2;
start_rule =
( "first" >> qi::int_
[ at_key<keys::first>(_val) = _1 ]
)
^
( "second" >> qi::int_
[ at_key<keys::second>(_val) = _1 ]
);
}
qi::rule< iter_type, Couple(), ascii::space_type > start_rule;
};
int main() {
Couple couple;
string example = "second 2 first 1";
iter_type begin( example.begin() );
iter_type end( example.end() );
// test at_key -- compiles with no error
at_key<keys::second>(couple) = 5;
bool ok = qi::phrase_parse( begin, end, G(), ascii::space, couple );
if ( ok )
cout << couple.a << " " << couple.b << endl;
else
cout << "Parse failed" << endl;
return 0;
}
The problem is that the code does not compile (Boost 1.50.0, g++ 4.5.0, MinGW), apparently fails at the at_key<> rules:
In file included from D:\projects\workspace\boost/boost/fusion/support/category_of.hpp:10:0,
from D:\projects\workspace\boost/boost/fusion/include/category_of.hpp:10,
from D:\projects\workspace\boost/boost/proto/fusion.hpp:20,
from D:\projects\workspace\boost/boost/proto/core.hpp:21,
from D:\projects\workspace\boost/boost/proto/proto.hpp:12,
from D:\projects\workspace\boost/boost/spirit/home/support/meta_compiler.hpp:19,
from D:\projects\workspace\boost/boost/spirit/home/qi/meta_compiler.hpp:14,
from D:\projects\workspace\boost/boost/spirit/home/qi/action/action.hpp:14,
from D:\projects\workspace\boost/boost/spirit/home/qi/action.hpp:14,
from D:\projects\workspace\boost/boost/spirit/home/qi.hpp:14,
from D:\projects\workspace\boost/boost/spirit/include/qi.hpp:16,
from ..\src\spirit02_test.cpp:11:
D:\projects\workspace\boost/boost/fusion/support/detail/category_of.hpp: In instantiation of 'boost::fusion::detail::fusion_category_of<const boost::phoenix::actor<boost::spirit::attribute<0> > >':
D:\projects\workspace\boost/boost/fusion/support/category_of.hpp:44:58: instantiated from 'boost::fusion::extension::category_of_impl<boost::fusion::non_fusion_tag>::apply<const boost::phoenix::actor<boost::spirit::attribute<0> > >'
D:\projects\workspace\boost/boost/fusion/support/category_of.hpp:66:9: instantiated from 'boost::fusion::traits::category_of<const boost::phoenix::actor<boost::spirit::attribute<0> > >'
D:\projects\workspace\boost/boost/fusion/support/category_of.hpp:73:9: instantiated from 'boost::fusion::traits::is_associative<const boost::phoenix::actor<boost::spirit::attribute<0> > >'
D:\projects\workspace\boost/boost/mpl/if.hpp:67:11: instantiated from 'boost::mpl::if_<boost::fusion::traits::is_associative<const boost::phoenix::actor<boost::spirit::attribute<0> > >, boost::fusion::result_of::key_of<mpl_::arg<1> >, boost::fusion::result_of::value_of<mpl_::arg<1> > >'
D:\projects\workspace\boost/boost/fusion/algorithm/query/find.hpp:45:9: instantiated from 'boost::fusion::result_of::find<const boost::phoenix::actor<boost::spirit::attribute<0> >, keys::first>'
D:\projects\workspace\boost/boost/fusion/sequence/intrinsic/at_key.hpp:38:17: instantiated from 'boost::fusion::extension::at_key_impl<boost::fusion::non_fusion_tag>::apply<const boost::phoenix::actor<boost::spirit::attribute<0> >, keys::first>'
D:\projects\workspace\boost/boost/fusion/sequence/intrinsic/at_key.hpp:71:9: instantiated from 'boost::fusion::result_of::at_key<const boost::phoenix::actor<boost::spirit::attribute<0> >, keys::first>'
..\src\spirit02_test.cpp:54:35: instantiated from here
D:\projects\workspace\boost/boost/fusion/support/detail/category_of.hpp:15:38: error: no type named 'category' in 'const struct boost::phoenix::actor<boost::spirit::attribute<0> >'
In file included from D:\projects\workspace\boost/boost/proto/args.hpp:21:0,
from D:\projects\workspace\boost/boost/proto/core.hpp:14,
from D:\projects\workspace\boost/boost/proto/proto.hpp:12,
from D:\projects\workspace\boost/boost/spirit/home/support/meta_compiler.hpp:19,
from D:\projects\workspace\boost/boost/spirit/home/qi/meta_compiler.hpp:14,
from D:\projects\workspace\boost/boost/spirit/home/qi/action/action.hpp:14,
from D:\projects\workspace\boost/boost/spirit/home/qi/action.hpp:14,
from D:\projects\workspace\boost/boost/spirit/home/qi.hpp:14,
from D:\projects\workspace\boost/boost/spirit/include/qi.hpp:16,
from ..\src\spirit02_test.cpp:11:
D:\projects\workspace\boost/boost/mpl/if.hpp: In instantiation of 'boost::mpl::if_<boost::fusion::traits::is_associative<const boost::phoenix::actor<boost::spirit::attribute<0> > >, boost::fusion::result_of::key_of<mpl_::arg<1> >, boost::fusion::result_of::value_of<mpl_::arg<1> > >':
D:\projects\workspace\boost/boost/fusion/algorithm/query/find.hpp:45:9: instantiated from 'boost::fusion::result_of::find<const boost::phoenix::actor<boost::spirit::attribute<0> >, keys::first>'
D:\projects\workspace\boost/boost/fusion/sequence/intrinsic/at_key.hpp:38:17: instantiated from 'boost::fusion::extension::at_key_impl<boost::fusion::non_fusion_tag>::apply<const boost::phoenix::actor<boost::spirit::attribute<0> >, keys::first>'
D:\projects\workspace\boost/boost/fusion/sequence/intrinsic/at_key.hpp:71:9: instantiated from 'boost::fusion::result_of::at_key<const boost::phoenix::actor<boost::spirit::attribute<0> >, keys::first>'
..\src\spirit02_test.cpp:54:35: instantiated from here
D:\projects\workspace\boost/boost/mpl/if.hpp:67:11: error: 'value' is not a member of 'boost::fusion::traits::is_associative<const boost::phoenix::actor<boost::spirit::attribute<0> > >'
D:\projects\workspace\boost/boost/mpl/if.hpp:70:41: error: 'value' is not a member of 'boost::fusion::traits::is_associative<const boost::phoenix::actor<boost::spirit::attribute<0> > >'
In file included from D:\projects\workspace\boost/boost/fusion/sequence/intrinsic.hpp:20:0,
from D:\projects\workspace\boost/boost/fusion/include/intrinsic.hpp:10,
from D:\projects\workspace\boost/boost/proto/fusion.hpp:22,
from D:\projects\workspace\boost/boost/proto/core.hpp:21,
from D:\projects\workspace\boost/boost/proto/proto.hpp:12,
from D:\projects\workspace\boost/boost/spirit/home/support/meta_compiler.hpp:19,
from D:\projects\workspace\boost/boost/spirit/home/qi/meta_compiler.hpp:14,
from D:\projects\workspace\boost/boost/spirit/home/qi/action/action.hpp:14,
from D:\projects\workspace\boost/boost/spirit/home/qi/action.hpp:14,
from D:\projects\workspace\boost/boost/spirit/home/qi.hpp:14,
from D:\projects\workspace\boost/boost/spirit/include/qi.hpp:16,
from ..\src\spirit02_test.cpp:11:
D:\projects\workspace\boost/boost/fusion/sequence/intrinsic/at_key.hpp: In instantiation of 'boost::fusion::extension::at_key_impl<boost::fusion::non_fusion_tag>::apply<const boost::phoenix::actor<boost::spirit::attribute<0> >, keys::first>':
D:\projects\workspace\boost/boost/fusion/sequence/intrinsic/at_key.hpp:71:9: instantiated from 'boost::fusion::result_of::at_key<const boost::phoenix::actor<boost::spirit::attribute<0> >, keys::first>'
..\src\spirit02_test.cpp:54:35: instantiated from here
D:\projects\workspace\boost/boost/fusion/sequence/intrinsic/at_key.hpp:38:17: error: no type named 'type' in 'struct boost::fusion::result_of::find<const boost::phoenix::actor<boost::spirit::attribute<0> >, keys::first>'
..\src\spirit02_test.cpp: In constructor 'G::G()':
..\src\spirit02_test.cpp:54:35: error: no matching function for call to 'at_key(const boost::spirit::_val_type&)'
In file included from D:\projects\workspace\boost/boost/fusion/sequence/intrinsic.hpp:20:0,
from D:\projects\workspace\boost/boost/fusion/include/intrinsic.hpp:10,
from D:\projects\workspace\boost/boost/proto/fusion.hpp:22,
from D:\projects\workspace\boost/boost/proto/core.hpp:21,
from D:\projects\workspace\boost/boost/proto/proto.hpp:12,
from D:\projects\workspace\boost/boost/spirit/home/support/meta_compiler.hpp:19,
from D:\projects\workspace\boost/boost/spirit/home/qi/meta_compiler.hpp:14,
from D:\projects\workspace\boost/boost/spirit/home/qi/action/action.hpp:14,
from D:\projects\workspace\boost/boost/spirit/home/qi/action.hpp:14,
from D:\projects\workspace\boost/boost/spirit/home/qi.hpp:14,
from D:\projects\workspace\boost/boost/spirit/include/qi.hpp:16,
from ..\src\spirit02_test.cpp:11:
D:\projects\workspace\boost/boost/fusion/sequence/intrinsic/at_key.hpp: At global scope:
D:\projects\workspace\boost/boost/fusion/sequence/intrinsic/at_key.hpp: In instantiation of 'boost::fusion::extension::at_key_impl<boost::fusion::non_fusion_tag>::apply<const boost::phoenix::actor<boost::spirit::attribute<0> >, keys::second>':
D:\projects\workspace\boost/boost/fusion/sequence/intrinsic/at_key.hpp:71:9: instantiated from 'boost::fusion::result_of::at_key<const boost::phoenix::actor<boost::spirit::attribute<0> >, keys::second>'
..\src\spirit02_test.cpp:58:36: instantiated from here
D:\projects\workspace\boost/boost/fusion/sequence/intrinsic/at_key.hpp:38:17: error: no type named 'type' in 'struct boost::fusion::result_of::find<const boost::phoenix::actor<boost::spirit::attribute<0> >, keys::second>'
..\src\spirit02_test.cpp: In constructor 'G::G()':
..\src\spirit02_test.cpp:58:36: error: no matching function for call to 'at_key(const boost::spirit::_val_type&)'
If I use a simpler rule (without associativity), everything compiles and works fine, but this solution is somewhat fragile:
// A non-associative solution
//start_rule %= ( ("first" >> qi::int_) ^ ("second" >> qi::int_) );
Why cannot I use at_key in the semantic action? Is there a better way to do an "associative" parse into a non-associative structure?
You need a lazy version of at_key. The patch for this sadly never made it into Spirit (yet):
/*=============================================================================
Copyright (c) 2005-2008 Hartmut Kaiser
Copyright (c) 2005-2007 Joel de Guzman
Copyright (c) 2011 Michael Caisse
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
==============================================================================*/
#ifndef PHOENIX_SEQUENCE_AT_KEY_HPP
#define PHOENIX_SEQUENCE_AT_KEY_HPP
#include <boost/fusion/include/at_key.hpp>
#include <boost/spirit/home/phoenix/core/actor.hpp>
#include <boost/spirit/home/phoenix/core/compose.hpp>
#include <boost/type_traits/remove_reference.hpp>
namespace boost { namespace phoenix
{
template <typename Key>
struct at_key_eval
{
template <typename Env, typename Tuple>
struct result
{
typedef typename Tuple::template result<Env>::type tuple;
typedef typename
fusion::result_of::at_key<
typename remove_reference<tuple>::type, Key
>::type
type;
};
template <typename RT, typename Env, typename Tuple>
static RT
eval(Env const& env, Tuple const& t)
{
return fusion::at_key<Key>(t.eval(env));
}
};
template <typename Key, typename Tuple>
inline actor<typename as_composite<at_key_eval<Key>, Tuple>::type>
at_key(Tuple const& tup)
{
return compose<at_key_eval<Key> >(tup);
}
}}
#endif
If you add it, you can use boost::phoenix::at_key:
using boost::phoenix::at_key;
Things will compile and work as expected. The linked patch also modifies boost/spirit/home/phoenix/fusion.hpp to include this new header, of course.