boost mpl fold placeholder expression fails to compile - c++

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

Related

Recursive unordered_map

I have a tree structure that internally uses unordered map
#include <unordered_map>
struct Node {
std::unordered_map<int, Node> children;
};
int main() {
Node a;
}
It works just fine on Apple clang 11.0.3 and MSVC v19.24, but it fails to compile on clang 10.0.0 and gcc 10.1
While regular std::map works just fine on all compilers. I failed to find the reason for this discrepancy. Is there any way to use std::unordered_map as a value for itself? Or pointers is the only solution here?
Here's the compiler explorer link https://godbolt.org/z/6eYch9
Here's an error from gcc:
#3 with x86-64 gcc 10.1
In file included from /opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/unordered_map:43,
from <source>:1:
/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/stl_pair.h:
In instantiation of 'struct std::pair<const int, Node>':
/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/ext/aligned_buffer.h:91:28:
required from 'struct __gnu_cxx::__aligned_buffer<std::pair<const int,
Node> >'
/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/hashtable_policy.h:233:43:
required from 'struct
std::__detail::_Hash_node_value_base<std::pair<const int, Node> >'
/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/hashtable_policy.h:279:12:
required from 'struct std::__detail::_Hash_node<std::pair<const int,
Node>, false>'
/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/hashtable_policy.h:1973:13:
required from 'struct
std::__detail::_Hashtable_alloc<std::allocator<std::__detail::_Hash_node<std::pair<const
int, Node>, false> > >'
/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/hashtable.h:173:11:
required from 'class std::_Hashtable<int, std::pair<const int, Node>,
std::allocator<std::pair<const int, Node> >,
std::__detail::_Select1st, std::equal_to<int>, std::hash<int>,
std::__detail::_Mod_range_hashing,
std::__detail::_Default_ranged_hash,
std::__detail::_Prime_rehash_policy,
std::__detail::_Hashtable_traits<false, false, true> >'
/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/unordered_map.h:105:18:
required from 'class std::unordered_map<int, Node>'
<source>:4:39: required from here
/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/stl_pair.h:218:11:
error: 'std::pair<_T1, _T2>::second' has incomplete type
218 | _T2 second; ///< The second member
| ^~~~~~
<source>:3:8: note: forward declaration of 'struct Node'
3 | struct Node {
| ^~~~
Compiler returned: 1
STL containers are not required to work with incomplete types. If you don't mind extra indirection, then the workaround is std::map<int, std::unique_ptr<Node>>
It's the same problem as doing e.g.
struct Node
{
Node child; // An instance of the full structure
};
You can't use a structure (or class) before it's fully defined, which it is at the closing }.
You can however define pointers to the structure, because then the compiler don't need the full structure definition, only know the name of the structure:
struct Node
{
Node* child; // Pointer to the structure
};
So to solve your problem, you need a map of pointers:
std::unordered_map<int, Node*> children;
Running into this while coding a Trie data structure I've noticed that in the latest of clang (v14) and GCC (v12) I don't get the error and my code operates as expected but anything below those versions (on godbolt.com) I get the same error. This is all using -std=c++14 so it's should not be related to the standard.

Seqan mini-bowtie example not compiling

I try to copy the example of mini-bowtie from the Seqan Web site.
Note that the example comes from version 1.4.2, not the current one.
When I compile, I have an error.
The minimal reproducible example is:
#include <seqan/index.h>
#include <seqan/store.h>
using namespace seqan;
int main()
{
typedef Index<StringSet<Dna5String>, FMIndex<> > TIndex;
typedef Iterator<TIndex, TopDown<ParentLinks<> > >::Type TIter;
FragmentStore<> fragStore;
StringSet<Dna5String> text;
TIndex fmIndex(text);
TIter it(fmIndex);
it = TIter(fmIndex); // This does not work
return 0;
}
The compiling error is quite long.
It starts with:
In file included from test.cpp:1:
In file included from /usr/include/seqan/index.h:172:
/usr/include/seqan/index/index_fm_stree.h:469:16: error: no matching constructor for initialization of 'TVertexDescriptor' (aka 'VertexFM<unsigned long, seqan::SimpleType<unsigned char, seqan::Dna5_> >')
return TVertexDescriptor(back(it.history).range, back(it.history).repLen, back(it.history).lastChar);
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/seqan/index/index_esa_stree.h:245:27: note: in instantiation of function template specialization 'seqan::nodeUp<seqan::StringSet<seqan::String<seqan::SimpleType<unsigned char, seqan::Dna5_>,
seqan::Alloc<void> >, seqan::Owner<seqan::Tag<seqan::Default_> > >, void, seqan::FMIndexConfig<void, unsigned long, 1, 1>, seqan::Preorder>' requested here
_parentDesc = nodeUp(_origin);
^
/usr/include/seqan/index/index_esa_stree.h:366:29: note: in instantiation of function template specialization 'seqan::Iter<seqan::Index<seqan::StringSet<seqan::String<seqan::SimpleType<unsigned char,
seqan::Dna5_>, seqan::Alloc<void> >, seqan::Owner<seqan::Tag<seqan::Default_> > >, seqan::FMIndex<void, seqan::FMIndexConfig<void, unsigned long, 1, 1> > >, seqan::VSTree<seqan::TopDown<seqan::Preorder> >
>::operator=<seqan::ParentLinks<seqan::Preorder> >' requested here
*(TBase*)(this) = _origin;
^
test.cpp:17:8: note: in instantiation of member function 'seqan::Iter<seqan::Index<seqan::StringSet<seqan::String<seqan::SimpleType<unsigned char, seqan::Dna5_>, seqan::Alloc<void> >,
seqan::Owner<seqan::Tag<seqan::Default_> > >, seqan::FMIndex<void, seqan::FMIndexConfig<void, unsigned long, 1, 1> > >, seqan::VSTree<seqan::TopDown<seqan::ParentLinks<seqan::Preorder> > > >::operator='
requested here
it = TIter(fmIndex);
^
It seems that the API has slightly changed, but I cannot exactly put the finger on it.
I compile with:
clang++ -Wall -Wextra -Weffc++ -O2 -o testSeqan test.cpp -lrt
with clang++ 6.0.0-1ubuntu2 x86_64-pc-linux-gnu, but g++ Ubuntu 7.3.0-16ubuntu3 gives similar (albeit less readable) results, and Seqan version 2.3.2.
What should I change?

compile error for boost::date_time::days_until_weekday

I'm currently toying around with boost::date_time. While doing so, I came upon the days_until_weekday (documentation link) function which appears highly useful to me. Unfortunately, I get a compile time error from the following snippet
date f(date d){
return next_weekday(d, boost::date_time::weekdays::Friday);
}
reading
> In file included from
> /usr/include/boost/date_time/gregorian/gregorian_types.hpp:25:0,
> from /usr/include/boost/date_time/posix_time/posix_time_config.hpp:18,
> from /usr/include/boost/date_time/posix_time/posix_time_system.hpp:13,
> from /usr/include/boost/date_time/posix_time/ptime.hpp:12,
> from /usr/include/boost/date_time/posix_time/posix_time.hpp:15,
> from prog.cpp:3: /usr/include/boost/date_time/date_generators.hpp: In instantiation of
> 'typename date_type::duration_type
> boost::date_time::days_until_weekday(const date_type&, const
> weekday_type&) [with date_type = boost::gregorian::date; weekday_type
> = boost::date_time::weekdays; typename date_type::duration_type = boost::gregorian::date_duration]':
> /usr/include/boost/date_time/date_generators.hpp:488:34: required
> from 'date_type boost::date_time::next_weekday(const date_type&, const
> weekday_type&) [with date_type = boost::gregorian::date; weekday_type
> = boost::date_time::weekdays]' prog.cpp:11:67: required from here /usr/include/boost/date_time/date_generators.hpp:452:37: error:
> request for member 'as_number' in 'wd', which is of non-class type
> 'const boost::date_time::weekdays'
> duration_type dd(wd.as_number() - d.day_of_week().as_number());
Go here for a paste of my code.
As the snippet causing the error is so short, I'm really out of ideas to fix this.
By the way, I'm on boost 1.60.0 using clang 3.7.0.
You need to convert the date_time enum to an object that matches the interface expected by the weekday_type passed to the function. Use the greg_weekday function to do this for you, eg:
return next_weekday(d, boost::gregorian::greg_weekday(boost::date_time::Friday));
That compiles for me under VS2015 and boost 1.53.
A link to the documentation for this function:
greg_weekday

Boost graph library causing errors when applying dijkstra's algorithm

I have been loosely following this example, this one, and this stack overflow post to try to apply Dijkstra's algorithm to find the cost of the shortest path between two nodes.
If I try to follow the first example, I get an error with the typedef statement for NameMap. This error is cryptic, verbose, and I don't quite know what to do with it.
If I try to follow the second example (copy-pasted from the Boost documentation!!) it does not compile. The error is even more cryptic and verbose.
The third one (the stack overflow post) relies on the same typedef as the first one.
Is this user error? It probably is, but how should I interpret an error message that spawns from the library code?
Update 1
I am using g++ (Debian 4.8.2-21) 4.8.2 from debian testing.
Update 2
Here is a condensed version of the source code that doesn't work. There are two lines prefaced by "// The following line causes an error" are the ones in question.
Update 3
I have changed
typedef adjacency_list<listS, vecS, directedS, allow_parallel_edge_tag, EdgeWeightProperty> Graph;
typedef adjacency_list<listS, vecS, directedS, no_property , EdgeWeightProperty> Graph;
Your first attempt didn't define a property with the vertex_name_t tag (or pass it as a adjacency_list template parameter), so when you try to create a property_map with that tag the compiler emits an error.
Your code:
typedef property<edge_weight_t, Weight> EdgeWeightProperty;
typedef boost::adjacency_list<listS, vecS, directedS, allow_parallel_edge_tag, EdgeWeightProperty> Graph;
// ^ What's this?
The example code you cited:
typedef boost::property<boost::edge_weight_t, Weight> WeightProperty;
typedef boost::property<boost::vertex_name_t, std::string> NameProperty; // <-- not in your code
typedef boost::adjacency_list < boost::listS, boost::vecS, boost::directedS, NameProperty, WeightProperty > Graph;
// ^ Used here
I have no idea why you are passing allow_parallel_edge_tag as a template parameter. If I'm reading the documentation correctly, that struct is designed for parallel_edge_traits specializations when you are using custom container types.
Edit: The second case is actually easy to diagnose once you have the code. Going through the error messages emitted by the compiler, we look for reasons why the compiler didn't select the 3-parameter overload for dijkstra_shortest_paths. A lot of the messages merely tells you that it rejected overloads with about a dozen parameters - as it should!
Now, this error message (emitted by g++ using Coliru) is pertinent, because it tells you why compiler rejected the three-parameter version:
In file included from main.cpp:5:0:
/usr/local/include/boost/graph/dijkstra_shortest_paths.hpp:602:3: note: void boost::
dijkstra_shortest_paths(const VertexListGraph&, typename boost::graph_traits<Graph>::
vertex_descriptor, const boost::bgl_named_params<T, Tag, Base>&) [ /* irrelevant stuff
telling you how it deduced the template parameters here */ ] <near match>
dijkstra_shortest_paths
^
/usr/local/include/boost/graph/dijkstra_shortest_paths.hpp:602:3: note: no known conversion for
argument 2 from 'long int [6]' to 'boost::graph_traits<boost::adjacency_list<boost::listS,
boost::vecS, boost::directedS, boost::no_property, boost::property<boost::edge_weight_t, long int> >
>::vertex_descriptor {aka long unsigned int}'
You passed s, the array containing source vertices, as the second parameter designating the starting vertex, when you should have passed v0, and the compiler is rightfully complaining that it cannot convert an array of longs to a single vertex.

generate fusion::vector from mpl::vector

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.