How to generate fusion::vector from mpl::vector?
How to generate mpl::vector from fusion::vector?
BOOST_MPL_ASSERT((is_same<
fusion::vector<int, char>,
generate_fusion_vector<mpl::vector<int, char> >::type >));
BOOST_MPL_ASSERT((is_same<
mpl::vector<int, char>,
generate_mpl_vector<fusion::vector<int, char> >::type >));
I need generate_fusion_vector and generate_mpl_vector metafunctions.
I can write my own metafunctions, but i suspect that they already exist.
I had an experience of generating fusion::map with help result_of::as_map before, but in current boost(trunk, 1.39 also) such error occur:
D:\Libraries\boost_trunk\boost/fusion/sequence/intrinsic/size.hpp(56) : error C2903: 'apply' : symbol is neither a class template nor a function template
D:\Libraries\boost_trunk\boost/fusion/container/vector/convert.hpp(23) : see reference to class template instantiation 'boost::fusion::result_of::size' being compiled
with
[
Sequence=boost::mpl::vector
]
temp.cpp(71) : see reference to class template instantiation 'boost::fusion::result_of::as_vector' being compiled
I don't understand what is going on?
As fusion accepts mpl types as arguments to functions you could try this:
BOOST_MPL_ASSERT((is_same<
fusion::vector<int, char>,
fusion::result_of::as_vector<mpl::vector<int, char> >::type >));
Edit:
I think the reason this isn't working for you is that you have to include certain header files to enable mpl compatibility in fusion.
#include <boost/fusion/adapted/mpl.hpp>
#include <boost/fusion/include/mpl.hpp>
I don't know if you're still doing char,int but I ran into the same error and my problem was that I tried to make a length 11 vector, but FUSION_MAX_VECTOR_SIZE was 10.
Related
I'm using templates while implementing AVL trees on Ubuntu.
The file will not compile when I write template class AVLTree<std::list<int> >;, it tells me:
undefined reference to `AVLTree < std::__cxx11::list < std::__cxx11::basic_string < char, std::char_traits < char>, std::allocator < char> >, std::allocator < std::__cxx11::basic_string < char, std::char_traits < char>, std::allocator < char> > > > >::insert(std::__cxx11::basic_string < char, std::char_traits < char>, std::allocator < char> >)'
And I don't get what it doesn't have the reference to.
But it compiles just fine when I write template class AVLTree<std::list<string> >;
I need to let AVLTree store linked lists that store string values.
Why does one compile and the other doesn't? How to solve my problem?
PS: I've included <list>, <string>, and <iostream>, along with my own header file.
Examining the error message closely shows that linker cannot find the AVLTree::insert(string) method.
Based on the sparse information that you posted, my best hypothesis is that you changed the template parameter in the following line from list<string> to list<int>:
template class AVLTree<std::list<string>>;
This line of code explicitly tells the compiler to instantiate a version of the AVLTree template using list<string> as the template parameter. Thus, when you try to compile the code after the change it gives you the error message that it cannot find the AVLTree::insert(string) function because the compiler is now generating the code for list<int> instead.
Your program contains other code that is referencing AVLTree<list<string>>. At a minimum you will have to update that code to use list<int> as well.
Plus, if you simplify the problem down to something you can post the code for on this site, then you will either find the issue during that process or at least have a change of getting a good answer.
The problem that I have encountered is the following warning from clang (c++14):
Pack expansion contains parameter pack 'v_seconds' that has a different length (3 vs. 1) from outer parameter packs
The issue is encountered in the following example code:
template<typename... v_firsts>
struct types_list {
template<typename... v_seconds>
using pairs_list = types_list<std::pair<v_firsts, v_seconds>...>;
};
using my_types_list = types_list<short, int, long>;
using my_pairs_list = my_types_list::pairs_list<short, int, long>; // GOOD
template<typename... v_pack>
using any_pairs_list = my_types_list::pairs_list<v_pack...>; // BAD
How I interpret the error is that somehow a specialization of any_pairs_list in which v_seconds has a length of 1 is encountered, and then naturally an error is encountered.
However the code above is the entire example code - I never use a specialization of any_pairs_list.
So, I have to conclude that a specialization is nevertheless created...
Now, the usual TMP forking question:
if (This an intentional behavior of the variadic syntax) {
Can someone reference some documentation so that I can learn more?
} else if (This a known clang decision or problem) {
Can someone reference some discussion?
} else {
Can someone please name the issue / mistake?
}
P.S. I have tested using apple's installation of Clang (v8.1.0) and also with Visual Studio 2017 Clang extension. Unfortunately I don't have a linux environment to test in...
My best guess is that Clang uses some type of heuristic to check for inherently uninstantiable templates. Perhaps it (spuriously) decides that there is one argument to the alias in any_pairs_list because it doesn't deal with pack expansions properly, and then substitutes some unique synthesized type to test whether that could work in principle. After all, you do get the exact same error message if you don't use a pack but just one bog-standard template parameter.
Reported as #32905.
Not a solution but a workaround. Make pairs_list a struct with a member typedef named, for example, type. Since this works I would say that this is a bug in the using alias template in Clang.
#include <iostream>
#include <utility>
template<typename... v_firsts>
struct types_list {
template<typename... v_seconds>
struct pairs_list {
typedef types_list<std::pair<v_firsts, v_seconds>...> type;
};
};
using my_types_list = types_list<short, int, long>;
using my_pairs_list = my_types_list::pairs_list<short, int, long>::type;
template<typename... v_pack>
using any_pairs_list = typename my_types_list::pairs_list<v_pack...>::type;
// Let's see what has been deduced
template < typename T >
void show_signature() { std::cout << __PRETTY_FUNCTION__ << '\n'; }
int main() {
show_signature<my_types_list>(); // T = types_list<short, int, long>
show_signature<my_pairs_list>(); // T = types_list<std::pair<short, short>, std::pair<int, int>, std::pair<long, long> >
show_signature<any_pairs_list<int,long,double>>(); // T = types_list<std::pair<short, int>, std::pair<int, long>, std::pair<long, double> >
}
I'm trying to compile the Statemachine example from boost-mpl (located in libs/mpl/examples/fsm/player2.cpp), but it fails with boost version 1.37 and g++ 4.8.2. With boost version 1.56 and the same compiler, the build succeeds. Unfortunately, due to some platform constraints, I cannot switch to version 1.56.
I'm not expecting anyone to look into the above mentioned lengthy example, therefore I identified a minimal code snippet which illustrates the problem:
#include <boost/mpl/fold.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/placeholders.hpp>
namespace mpl = boost::mpl;
using namespace mpl::placeholders;
//Basic queue datatype
template< class CURRENT, class NEXT >
struct queue_element
{
typedef typename CURRENT::mytype mytype;
};
//type to be put at the end of the queue
struct default_queue_element
{
};
template <class TYPE>
struct wrapper{
typedef TYPE mytype;
};
typedef mpl::vector<wrapper<int>, wrapper<char> > myvector;
//the following fold expression should create this type:
typedef queue_element<wrapper<char>, queue_element<wrapper<int>,
default_queue_element> > this_type_should_be_created;
//This typedef fails to compile with boost Version 1.37,
//but works perfectly with version 1.56
typedef typename
mpl::fold<
myvector
,default_queue_element
,queue_element<_2,_1>
>::type
generate_queue;
With boost 1.37, g++ issues the following errors:
foldtest2.cpp: In instantiation of ‘struct queue_element<mpl_::arg<2>, mpl_::arg<1> >’:
../boost_1_37_0/boost/mpl/aux_/preprocessed/gcc/template_arity.hpp:85:5: required from ‘const int boost::mpl::aux::template_arity_impl<queue_element<mpl_::arg<2>, mpl_::arg<1> >, 1>::value’
../boost_1_37_0/boost/mpl/aux_/preprocessed/gcc/template_arity.hpp:93:5: required from ‘const int boost::mpl::aux::template_arity<queue_element<mpl_::arg<2>, mpl_::arg<1> > >::value’
../boost_1_37_0/boost/mpl/aux_/preprocessed/gcc/template_arity.hpp:98:30: required from ‘struct boost::mpl::aux::template_arity<queue_element<mpl_::arg<2>, mpl_::arg<1> > >’
../boost_1_37_0/boost/mpl/aux_/preprocessed/gcc/apply.hpp:67:8: required from ‘struct boost::mpl::apply2<queue_element<mpl_::arg<2>, mpl_::arg<1> >, default_queue_element, wrapper<int> >’
../boost_1_37_0/boost/mpl/aux_/preprocessed/gcc/fold_impl.hpp:67:85: required from ‘struct boost::mpl::aux::fold_impl<2, boost::mpl::v_iter<boost::mpl::vector<wrapper<int>, wrapper<char> >, 0l>, boost::mpl::v_iter<boost::mpl::vector<wrapper<int>, wrapper<char> >, 2l>, default_queue_element, queue_element<mpl_::arg<2>, mpl_::arg<1> > >’
../boost_1_37_0/boost/mpl/fold.hpp:39:18: required from ‘struct boost::mpl::fold<boost::mpl::vector<wrapper<int>, wrapper<char> >, default_queue_element, queue_element<mpl_::arg<2>, mpl_::arg<1> > >’
foldtest2.cpp:39:6: required from here
foldtest2.cpp:15:38: error: no type named ‘mytype’ in ‘struct mpl_::arg<2>’
typedef typename CURRENT::mytype mytype;
Is there a work-around to make the code compile with boost 1.37? I have been searching the web for quite some time. If nevertheless the question has already been answered somewhere, I would be grateful if you could point that out.
Looks to be very simply a bug in that ancient(¹) version of boost.
A quick bisection tells me it was fixed in v1.43.0(²). Release notes don't disclose the secret, but git does:
c5621d9 MPL: merge fix for ticket #1992 boost::mpl::zip_view does not support use as a metafunction with ::type
31a2c78 MPL: merge fix for ticket #4061 [MPL] gcc-4.5 compilation problems related to arity_helper
It clearly appears to be the latter (confirmed by compiling against 31a2c78).
So your fix this single line in include/boost/mpl/aux_/template_arity.hpp(³):
sizeof(arity_helper(type_wrapper<F>(),arity_tag<N>())) - 1
should be
sizeof(::boost::mpl::aux::arity_helper(type_wrapper<F>(),arity_tag<N>())) - 1
Of course the proper way to fix this is to use a supported version of boost
¹ (November 3rd, 2008)!!
² (May 6th, 2010)
³ warning: also present in several copies generated in preprocessed versions of the header
I want to use Boost.Units to represent a quantity expressed in grams per milliliter. I am trying to define the unit "milliliter". If I write
typedef boost::units::make_scaled_unit<
boost::units::si::volume,
boost::units::scale<10, boost::units::static_rational<-3> >
>::type liter;
typedef boost::units::make_scaled_unit<
liter,
boost::units::scale<10, boost::units::static_rational<-3> >
>::type milliliter;
the code compiles fine, but if I replace my own liter with boost::units::metric::liter_base_unit, then then definition of milliliter fails to compile with a "no type named 'type' in struct boost::units::make_scaled_unit" error.
Could you explain me why? Can the unit in make_scaled_unit be a base unit or do I need to make a derived unit from boost::units::metric::liter_base_unit?
I've found the solution. The problem is, as I suggested, that the unit in make_scaled_unit must be a unit type, not a base unit. By replacing boost::units::metric::liter_base_unit with boost::units::metric::liter_base_unit::unit_type, it works.
The code becomes:
typedef boost::units::make_scaled_unit<
boost::units::metric::liter_base_unit::unit_type,
boost::units::scale<10, boost::units::static_rational<-3> >
>::type milliliter;
I'm upgrading some C++ code from VisualStudio 6 towards VisualStudio 2008.
There is a class "GenExportableTree" which looks a lot like xtree from Dinkumware http://www.dinkumware.com/xtree.txt
When compiling the library which contains this GenExportableTree, I get the following error:
Error 37 error C2664: 'std::allocator<_Ty>::deallocate' : cannot convert
parameter 1 from 'std::CGenExportableTree<_K,_Ty,_Kfn,_Pr,_A>::_Node *' to
'CCfwSchemaInfo *'
which are the following lines:
void _Freenode(_Nodeptr _S)
{
allocator.deallocate( _S, 1);
}
Some extra info:
The you can find the complete implementation of the GenExportableTree under the dinkumware link above.
Where the CCfwSchemaInfo comes around the corner I can find following declarations:
typedef CGenExportableMap<wstring, CCfwSchemaInfo, GenNoCaseWString> CfwSchemaTable;
The definition of the CGenExportableMap is as follows:
template<class _K, class _Ty, class _Pr = less<_K>,
class _A = allocator<_Ty> >
class CGenExportableMap {
public:
typedef CGenExportableMap<_K, _Ty, _Pr, _A> _Myt;
typedef pair<const _K, _Ty> value_type;
....
....
typedef _K key_type;
typedef _Ty referent_type;
typedef _Pr key_compare;
typedef _A allocator_type;
typedef typename _A::reference _Tref;
typedef CGenExportableTree<_K, value_type, _Kfn, _Pr, _A> _Imp;
In this last line is where the GenExportableTree gets used in the GenExportableMap definition.
As this previously all compiled correctly under vs6, I guess actually everything is correct - probably the compiler is just more strictly now - so where should I start looking to find the error the compiler is complaining about? And how should i resolve this one?
Thanks!
VC6 had serious template problems so it couldn't support allocators according to the standard. They used a couple of special hacks that have long since been removed.
If some code still depends on those non-standard interfaces, I think your only option is to fix the code so it works with the current (standard) allocator interface. Sorry.