I'm trying to implement some numeric procedures using the boost multiprecision template library in combination with numeric bindings for a lapack backend.
However, the template resolution doesn't seem to work as intended. I've been able to narrow it down to this minimal example:
#include <boost/numeric/ublas/symmetric.hpp>
#include <boost/multiprecision/cpp_dec_float.hpp>
#include <boost/numeric/bindings/traits/ublas_matrix.hpp>
#include "boost/numeric/bindings/lapack/syev.hpp"
#include "boost/numeric/bindings/lapack/workspace.hpp"
typedef boost::multiprecision::number<boost::multiprecision::cpp_dec_float<100> > SuperFloat;
typedef std::numeric_limits<boost::multiprecision::cpp_dec_float<100> > SuperFloatPrecision;
typedef boost::numeric::ublas::matrix<SuperFloat> Matrix;
typedef boost::numeric::ublas::symmetric_matrix<SuperFloat> MatrixSym;
inline int diagonalize(Matrix& eigenvectors, boost::numeric::ublas::vector<SuperFloat>& eigenvalues) {
int r = boost::numeric::bindings::lapack::syev( 'U', eigenvectors, eigenvalues, boost::numeric::bindings::lapack::minimal_workspace() );
return r;
}
int main(){
std::cout << "hello!" << std::endl;
return 0;
}
which yields this error message:
boost/numeric/bindings/lapack/syev.hpp: In instantiation of ‘int boost::numeric::bindings::lapack::syev(char, A&, W&, boost::numeric::bindings::lapack::minimal_workspace) [with A = boost::numeric::ublas::matrix<boost::multiprecision::number<boost::multiprecision::backends::cpp_dec_float<100u> > >; W = boost::numeric::ublas::vector<boost::multiprecision::number<boost::multiprecision::backends::cpp_dec_float<100u> > >]’:
test.cxx:13:137: required from here
boost/numeric/bindings/lapack/syev.hpp:163:8: error: invalid application of ‘sizeof’ to incomplete type ‘boost::STATIC_ASSERTION_FAILURE<false>’
BOOST_STATIC_ASSERT( (boost::mpl::or_< boost::is_same< matrix_structure, traits::symmetric_t >
^
In file included from ./boost/numeric/bindings/traits/traits.hpp:18:0,
from ./boost/numeric/bindings/traits/ublas_matrix.hpp:17,
from test.cxx:3:
./boost/numeric/bindings/traits/matrix_traits.hpp: In instantiation of ‘char boost::numeric::bindings::traits::matrix_uplo_tag(SymmM&) [with SymmM = boost::numeric::ublas::matrix<boost::multiprecision::number<boost::multiprecision::backends::cpp_dec_float<100u> > >]’:
boost/numeric/bindings/lapack/syev.hpp:181:47: required from ‘int boost::numeric::bindings::lapack::syev(char, A&, W&, boost::numeric::bindings::lapack::minimal_workspace) [with A = boost::numeric::ublas::matrix<boost::multiprecision::number<boost::multiprecision::backends::cpp_dec_float<100u> > >; W = boost::numeric::ublas::vector<boost::multiprecision::number<boost::multiprecision::backends::cpp_dec_float<100u> > >]’
test.cxx:13:137: required from here
./boost/numeric/bindings/traits/matrix_traits.hpp:141:56: error: no type named ‘uplo_type’ in ‘struct boost::numeric::bindings::traits::matrix_traits<boost::numeric::ublas::matrix<boost::multiprecision::number<boost::multiprecision::backends::cpp_dec_float<100u> > > >’
typedef typename matrix_traits<SymmM>::uplo_type uplo_t;
Is it at all possible to use lapack as a backend for boost UBLAS templated to multiprecision, or is this a futile endeavour?
Are there any other ways to do, say, an eigenvector decomposition of a ublas multiprecision matrix?
Related
I'm new in using boost library, so I thanked every one that helps me.
#include "gmpxx.h"
#include <boost/multiprecision/gmp.hpp>
#include <boost/multiprecision/random.hpp>
#include <boost/multiprecision/number.hpp>
using namespace std;
using namespace boost::multiprecision;
using boost::multiprecision::mpz_int;
using boost::multiprecision::mpq_rational;
using boost::multiprecision::uint128_t;
using boost::multiprecision::uint256_t;
using boost::multiprecision::uint512_t;
using boost::multiprecision::uint1024_t;
using boost::multiprecision::mpf_float;
void testtmultiprecisions(){
mpq_rational b = boost::multiprecision::pow(mpf_float(1), mpf_float(2));
std::cout << typeid(b).name() << std::endl;
}
but i get compiler error like below :
error: conversion from boost::enable_if_c<true,
boost::multiprecision::detail::expression
<boost::multiprecision::detail::function,
boost::multiprecision::detail::pow_funct
<boost::multiprecision::backends::gmp_float<0u> >,
boost::multiprecision::number
<boost::multiprecision::backends::gmp_float<0u> >,
boost::multiprecision::number
<boost::multiprecision::backends::gmp_float<0u> >, void>
>::type {aka boost::multiprecision::detail::expression
<boost::multiprecision::detail::function,
boost::multiprecision::detail::pow_funct
<boost::multiprecision::backends::gmp_float<0u> >,
boost::multiprecision::number
<boost::multiprecision::backends::gmp_float<0u> >,
<boost::multiprecision::backends::gmp_float<0u> >, void>}
to non-scalar type â€کboost::multiprecision::mpq_rational {aka
boost::multiprecision::number
<boost::multiprecision::backends::gmp_rational,
(boost::multiprecision::expression_template_option)1u>}
requested
mpq_rational b = boost::multiprecision::pow(mpf_float(1), mpf_float(2));
i also changed above code :
mpq_rational b = boost::multiprecision::pow(mpf_float(1),
mpf_float(2)).covert_to<mpq_rational>();
and get new compiler errors :
[compiler error]
Rationals, by definition, have integral numerator and denominator.
Conversion of floating point to integral numbers is - again by definition - not lossless. The compiler will only compile conversions that are statically known to be lossless.
Also, conversions will not be chained (how would the library resolve ambiguous conversion paths?). In this case, you could help the compiler out using the intermediate step converting to the underlying type for mpq_rational (namely mpz_int):
#include <boost/multiprecision/gmp.hpp>
#include <boost/multiprecision/number.hpp>
#include <iostream>
using boost::multiprecision::mpq_rational;
using boost::multiprecision::mpz_int;
using boost::multiprecision::mpf_float;
int main() {
mpq_rational b = boost::multiprecision::pow(mpf_float(2), mpf_float(3)).convert_to<mpz_int>();
std::cout << b << "\n";
}
Prints
8
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);
}
};
};
I have the following code:
#include <algorithm>
#include <vector>
#include <iostream>
#include <stdio.h>
using namespace std;
int main()
{
typedef vector<int> IntContainer;
typedef IntContainer::iterator IntIterator;
IntContainer vw;
IntIterator i = find(vw.begin(), vw.end(), 5);
if (i != vw.end())
{
printf("Find 5 in vector\n"); // found it
}
else
{
printf("Couldn't find 5 in vector\n"); // couldn't found it
}
return 0;
}
I try to compile it on Ubuntu with gcc 4.7.1 and get the following error:
vec_test.cpp: In function ‘int main()’:
vec_test.cpp:27:46: error: no matching function for call to ‘find(std::vector<int>::iterator, std::vector<int>::iterator, int)’
vec_test.cpp:27:46: note: candidate is:
In file included from /usr/local/lib/gcc/i686-pc-linux-gnu/4.7.1/../../../../include/c++/4.7.1/bits/locale_facets.h:50:0,
from /usr/local/lib/gcc/i686-pc-linux-gnu/4.7.1/../../../../include/c++/4.7.1/bits/basic_ios.h:39,
from /usr/local/lib/gcc/i686-pc-linux-gnu/4.7.1/../../../../include/c++/4.7.1/ios:45,
from /usr/local/lib/gcc/i686-pc-linux-gnu/4.7.1/../../../../include/c++/4.7.1/ostream:40,
from /usr/local/lib/gcc/i686-pc-linux-gnu/4.7.1/../../../../include/c++/4.7.1/iostream:40,
from vec_test.cpp:3:
/usr/local/lib/gcc/i686-pc-linux-gnu/4.7.1/../../../../include/c++/4.7.1/bits/streambuf_iterator.h:371:5: note: template<class _CharT2> typename __gnu_cxx::__enable_if<std::__is_char<_CharT2>::__value, std::istreambuf_iterator<_CharT2, std::char_traits<_CharT> > >::__type std::find(std::istreambuf_iterator<_CharT2, std::char_traits<_CharT> >, std::istreambuf_iterator<_CharT2, std::char_traits<_CharT> >, const _CharT2&)
/usr/local/lib/gcc/i686-pc-linux-gnu/4.7.1/../../../../include/c++/4.7.1/bits/streambuf_iterator.h:371:5: note: template argument deduction/substitution failed:
vec_test.cpp:27:46: note: ‘__gnu_cxx::__normal_iterator<int*, std::vector<int> >’ is not derived from ‘std::istreambuf_iterator<_CharT2, std::char_traits<_CharT> >’
This code doesn't do anything since the vector is not initialized with any content but it should compile.
I suspect this is a gcc problem but after lots of digging I'm quit desperate.
Please let me know if anyone encountered this problem and knows how to solve it.
Maybe some file defines a function find in global namespace?
Have you tried specifying full-scope? That's to say, std::find instead of find. It could help deleting that weird line:
using namespace std;
However, it is not what I would expect. I would call it a bug.
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.
I would like to learn how to use binding functions.
Here is the idea:
I have this function which takes to parameters:
void print_i(int t, std::string separator)
{
std::cout << t << separator;
}
And I would like to do:
std::vector<int> elements;
// ...
for_each(elements.begin(), elements.end(), std::bind2nd(print_i, '\n'));
But it does not work !
Here is what I get:
/usr/include/c++/4.3/backward/binders.h: In instantiation of ‘std::binder2nd<void ()(int, std::string)>’:
main.cpp:72: instantiated from here
/usr/include/c++/4.3/backward/binders.h:138: error: ‘void ()(int, std::string)’ is not a class, struct, or union type
/usr/include/c++/4.3/backward/binders.h:141: error: ‘void ()(int, std::string)’ is not a class, struct, or union type
/usr/include/c++/4.3/backward/binders.h:145: error: ‘void ()(int, std::string)’ is not a class, struct, or union type
/usr/include/c++/4.3/backward/binders.h:149: error: ‘void ()(int, std::string)’ is not a class, struct, or union type
/usr/include/c++/4.3/backward/binders.h:155: error: ‘void ()(int, std::string)’ is not a class, struct, or union type
/usr/include/c++/4.3/backward/binders.h:140: error: field ‘std::binder2nd<void ()(int, std::string)>::op’ invalidly declared function type
/usr/include/c++/4.3/backward/binders.h: In function ‘std::binder2nd<_Operation> std::bind2nd(const _Operation&, const _Tp&) [with _Operation = void ()(int, std::string), _Tp = char]’:
main.cpp:72: instantiated from here
/usr/include/c++/4.3/backward/binders.h:164: error: ‘void ()(int, std::string)’ is not a class, struct, or union type
/usr/include/c++/4.3/bits/stl_algo.h: In function ‘_Funct std::for_each(_IIter, _IIter, _Funct) [with _IIter = __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, _Funct = std::binder2nd<void ()(int, std::string)>]’:
main.cpp:72: instantiated from here
/usr/include/c++/4.3/bits/stl_algo.h:3791: error: no match for call to ‘(std::binder2nd<void ()(int, std::string)>) (int&)’
make: *** [all] Error 1
I could use functor, but it is quicker to use binding.
Thanks!
You need to use a Copyable/Refrencable object, the following works:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <functional>
void print_i(int t, std::string separator)
{
std::cout << t << separator;
}
int main()
{
std::vector<int> elements;
std::string delim = "\n";
for_each(elements.begin(),
elements.end(),
std::bind2nd(std::ptr_fun(&print_i),delim));
return 0;
}
Normally you can get the same effect by simply doing the following:
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
int main()
{
std::vector<int> elements;
std::copy(elements.begin(),
elements.end(),
std::ostream_iterator<int>(std::cout,"\n"));
return 0;
}
Also assuming you have access to TR1 in the STL you're using, its always best to revise/replace any uses of bind1st and bind2nd with std::bind
The argument to bind2nd must be an AdaptableBinaryFunction. A plain binary function does not fulfill this requirement (an adaptable function required typedefs for its return and argument types, a plain function type does not provide any typedefs). You could use std::bind which is probably the better choice anyway.
You need to do the following steps:
1. create a struct (or class) that inherits from std::binary_function
2. define your predicate function in the operator() member function of the struct created in step 1
3. use bind2nd to bind an appropriate value to the struct created in step 1
I have done all this in an example. You can read the article and download the complete code on the following link: bind and find
These functions are deprecated since C++11 and removed in C++17. As mentioned in one comment above, the better solution now is to use std::bind and the placeholders:
void callable(int a, int b);
auto f = std::bind1st(&callable, 42); // returns a 1-arg function
becomes:
// returns a 1-arg function
auto f = std::bind(&callable, 42, std::placeholders::_1);