Cannot compile: error: expected primary-expression before '(' token - c++

I cannot get this compile:
// main.cpp
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/composite_key.hpp>
#include <boost/multi_index/indexed_by.hpp>
#include <boost/multi_index/mem_fun.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/tag.hpp>
using namespace boost::multi_index;
struct by_attrs{};
// Generic MultiIndex that wraps boost::multi_index
template<typename Container>
class MultiIndex
{
public:
typedef typename Container::template index<by_attrs>::type::iterator attr_iterator;
template<typename FromArgs, typename ToArgs>
std::pair<attr_iterator, attr_iterator>
fetch_range(FromArgs&& from, ToArgs&& to)
const
{
return std::pair<attr_iterator, attr_iterator>(
_container.get<by_attrs>().lower_bound(from),
_container.get<by_attrs>().upper_bound(to)
);
}
private:
Container _container;
};
class Foo
{
public:
int bar() const
{
return 1;
}
};
typedef multi_index_container<
Foo,
indexed_by<
ordered_unique<
tag<by_attrs>,
composite_key<
Foo,
const_mem_fun<
Foo,
int,
&Foo::bar
>
>
>
>
> FooMultiIndexContainer;
typedef MultiIndex<FooMultiIndexContainer> FooMultiIndex;
int main()
{
FooMultiIndex foo_index;
}
Error (g++ -std=c++11 main.cpp):
In member function 'std::pair<typename Container::index<by_attrs>::type::iterator, typename Container::index<by_attrs>::type::iterator> MultiIndex<Container>::fetch_range(FromArgs&&, ToArgs&&) const': main.cpp:28:55: error: expected primary-expression before '(' token 28 | return std::pair<attr_iterator, attr_iterator>(

You need to put a couple of templates here:
template<typename FromArgs, typename ToArgs>
std::pair<attr_iterator, attr_iterator>
fetch_range(FromArgs&& from, ToArgs&& to)
const
{
return std::pair<attr_iterator, attr_iterator>(
_container.template get<by_attrs>().lower_bound(from),
_container.template get<by_attrs>().upper_bound(to)
);
}
You may want to consult this thread on the use of typename and template in so-called dependent contexts: Where and why do I have to put the “template” and “typename” keywords?

Related

How to declare a self-referential template typedef

Here's a small example which is substantially similar to what I'm trying to do:
#include <boost/variant/variant.hpp>
#include <boost/variant/recursive_wrapper.hpp>
#include <utility>
#include <vector>
struct foo {
const char * str;
};
typedef std::pair<float, float> fpair;
//typedef std::vector<boost::variant<int, fpair, foo, vlist>> vlist;
// ^ No...
//typedef std::vector<boost::variant<int, fpair, foo, boost::recursive_wrapper<vlist>>> vlist;
// ^ No...
//template <typename T = vlist<T> >
//using vlist = std::vector<boost::variant<int, fpair, foo, boost::recursive_wrapper<vlist>>>;
// ^ No...
template <typename T = vlist<T> >
using vlist = std::vector<boost::variant<int, fpair, foo, boost::recursive_wrapper<T>>>;
// Still no?
int main () {
std::cout << "Hello world\n";
}
The error I get with gcc 4.8 is:
test.cpp:12:33: error: expected nested-name-specifier before ‘vlist’
template <typename T = typename vlist<T>>
^
test.cpp:12:33: error: expected ‘>’ before ‘vlist’
The error with clang 3.6 is:
test.cpp:12:24: error: unknown type name 'vlist'
template <typename T = vlist<T>>
^
test.cpp:12:29: error: expected ',' or '>' in template-parameter-list
template <typename T = vlist<T>>
^
test.cpp:12:32: error: expected unqualified-id
template <typename T = vlist<T>>
^
3 errors generated.
(Edit: actually these errors are from slightly different versions of the above code, but they all give quite similar messages)
I looked at these earlier, slightly different questions, I'm still stumped:
How to declare a self referencing template type
How to properly declare a self-referencing template type?
Boost Fusion adapt declaration for a templated self referential structure
Does anyone know a trick for this, or is there some reason I'm not aware of that the compiler inherently isn't able to do this?
I believe you just want boost::make_recursive_variant:
#include <boost/variant/variant.hpp>
#include <boost/variant/recursive_variant.hpp>
#include <utility>
#include <vector>
struct foo {
const char* str;
};
typedef std::pair<float, float> fpair;
typedef boost::make_recursive_variant<
int,
fpair,
foo,
std::vector<boost::recursive_variant_>
>::type vlist;
int main() {
std::vector<vlist> vec;
vec.push_back(4);
vec.push_back(fpair{1.0f, 2.0f});
vlist v2(vec);
}

How am I supposed to write a metafunction that works like the ones in MPL?

I seem to be missing something when trying to write a meta-function that calls into MPL code. The follow code fails to compile with the following error on inst2, but works fine on inst1:
error C2903: 'apply' : symbol is neither a class template nor a function template
using namespace boost::mpl;
template <typename VECTOR>
struct first_element : mpl::at_c<VECTOR, 0> {};
int main()
{
typedef vector<
vector<int, int>,
vector<int, int>,
vector<int, int>> lotso;
typedef mpl::transform<lotso,
first_element<_1>>::type inst1;
typedef first_element<
at_c<lotso,0>>::type inst2;
return 0;
}
I think you forgot a ::type behind the call to at_c inside the typedef for inst2. Recall that your first_element expects something on which at_c can be applied. The raw at_c<lotso, 0>, however, is not yet evaluated. Evaluating a metafunction is done by adding ::type.
#include <boost/mpl/vector.hpp>
#include <boost/mpl/at.hpp>
#include <boost/mpl/transform.hpp>
#include <boost/mpl/placeholders.hpp>
#include <type_traits>
using namespace boost;
using namespace boost::mpl;
template <typename VECTOR>
struct first_element : mpl::at_c<VECTOR, 0> {};
int main()
{
typedef vector<
vector<int, int>,
vector<int, int>,
vector<int, int>> lotso;
typedef mpl::transform<lotso,
first_element<_1>>::type inst1;
typedef first_element<
at_c<lotso,0>::type >::type inst2;
^^^^^^ <--- you forgot a ::type here
static_assert(std::is_same<first_element<inst1>::type, inst2>::value, "bingo");
return 0;
}
Live Example. As a further check, I verified that a further dereference on inst1 gives the same type as inst2.

boost multi index container of template-dependent struct in template-class

I want a multi-index-container in a class, that depends on a template-dependent class in the class.
Sounds complicated, here is the code:
#include <boost/unordered_map.hpp>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/random_access_index.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/member.hpp>
template <typename Type>
class myDataContainer{
public:
struct DataStruct{
double t;
std::vector<Type> data;
};
// indices structs
struct TagTime{};
struct TagOrdered{};
typedef boost::multi_index::multi_index_container<
DataStruct,
boost::multi_index::indexed_by<
boost::multi_index::hashed_unique<boost::multi_index::tag<TagTime>, boost::multi_index::member<DataStruct, double, &DataStruct::t> >,
boost::multi_index::ordered_unique<boost::multi_index::tag<TagOrdered>, boost::multi_index::member<DataStruct, double, &DataStruct::t> > // this index represents timestamp incremental order
>
> InnerDataContainer;
typedef typename boost::multi_index::index<InnerDataContainer,TagTime>::type timestamp_view;
typedef typename boost::multi_index::index<InnerDataContainer,TagOrdered>::type ordered_view;
InnerDataContainer dataContainer;
void begin(){
ordered_view& ordView = dataContainer.get<TagOrdered>();
ordView.begin();
}
};
int main(int argc, char *argv[])
{
myDataContainer<float> data;
myDataContainer<float>::ordered_view& ordView = data.dataContainer.get<TagOrder>();
ordView.begin();
}
Without the myDataContainer::begin() function this code compiles, but with the myDataContainer::begin() I get the following error:
main.cpp: In member function 'void myDataContainer<Type>::begin()':
main.cpp:134:66: error: expected primary-expression before '>' token
main.cpp:134:68: error: expected primary-expression before ')' token
Am I missing something? Is this a bug in boost or is it not possible?`
Thanks in advance
veio
Because dataContainer is template parameter dependent, you need
ordered_view& ordView = dataContainer.template get<TagOrdered>();
In main() you use specific a specialization, so there are no dependent expressions any more.

Boost multi_index_container, get index by tag results in compiler error

So, I'm trying to dabble with the multi_index_container and am having a rather strange compiler error, first here is the simplest example to demonstrate my problem (I'm probably missing something stupidly simple)...
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/sequenced_index.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/identity.hpp>
#include <boost/multi_index/mem_fun.hpp>
namespace multi_index = boost::multi_index;
template <typename _IdType>
class A
{
public:
typedef _IdType IdType;
IdType getId() const { return id; }
private:
IdType id;
};
struct id_index{};
template <typename Traits>
class Container
{
typedef typename Traits::AType AType;
typedef typename AType::IdType IdType;
typedef typename multi_index::multi_index_container<
AType,
multi_index::indexed_by<
// sort by Id
multi_index::ordered_non_unique<multi_index::tag<id_index>, BOOST_MULTI_INDEX_CONST_MEM_FUN(AType, IdType, getId) >
>
> ASet;
typedef typename ASet::template index<id_index>::type::const_iterator a_it;
typedef typename ASet::template index<id_index>::type::reverse_iterator a_rit;
typedef typename ASet::template index<id_index>::type id_index_t;
public:
bool addA(AType const& cA)
{
const id_index_t& os = _cSet.get<id_index>(); // line 1: errors occur here
// .. do stuff
return true;
}
private:
// Instance of the container...
ASet _cSet;
};
struct ATraits
{
typedef A<int> AType;
};
int main(void)
{
Container<ATraits> container;
ATraits::AType a;
container.addA(a);
return 0;
}
The errors reported by g++ (gcc 4.4.4, linux) is:
error: expected primary-expression before ‘>’ token (# line 1)
error: expected primary-expression before ‘)’ token (# line 1)
So this was working fine till I converted the Container to a class template, after this, I get this error, and can't work out why..
Any ideas will be appreciated...
bool addA(AType const& cA)
{
const id_index_t& os = _cSet.template get<id_index>(); // line 1: errors occur here
// .. do stuff
return true;
}

C++ templated functor in lambda expression

This first piece has been solved by Eric's comments below but has led onto a secondary issue that I describe after the horizontal rule. Thanks Eric!
I'm trying to pass a functor that is a templated class to the create_thread method of boost thread_group class along with two parameters to the functor. However I can't seem to get beyond my current compile error. With the below code:
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
#include <boost/thread.hpp>
#include <vector>
using namespace boost::lambda;
using namespace std;
namespace bl = boost::lambda;
template<typename ftor, typename data>
class Foo
{
public:
explicit Foo()
{
}
void doFtor ()
{
_threads.create_thread(bind(&Foo<ftor, data>::_ftor, _list.begin(), _list.end()));
//_threads.create_thread(bind(_ftor, _list.begin(), _list.end()));
_threads.join_all();
}
private:
boost::thread_group _threads;
ftor _ftor;
vector<data> _list;
};
template<typename data>
class Ftor
{
public:
//template <class Args> struct sig { typedef void type; }
explicit Ftor () {}
void operator() (typename vector<data>::iterator &startItr, typename vector<data>::iterator &endItr)
{
for_each(startItr, endItr, cout << bl::_1 << constant("."));
}
}
I also tried typedef-ing 'type' as I thought my problem might have something to do with the Sig Template as the functor itself is templated.
The error I am getting is:
error: no matching function for call to ‘boost::lambda::function_adaptor<Ftor<int> Foo<Ftor<int>, int>::*>::apply(Ftor<int> Foo<Ftor<int>, int>::* const&, const __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int>> >&, const __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >&)’
with a bunch of preamble beforehand.
Thanks in advance for any help!
Okay I've modified the code taking in Eric's suggestions below resulting in the following code:
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
#include <boost/thread.hpp>
#include <vector>
using namespace boost::lambda;
using namespace std;
namespace bl = boost::lambda;
template<typename ftor, typename data>
class Foo
{
public:
explicit Foo()
{
}
void doFtor ()
{
_threads.create_thread(bl::bind(boost::ref(_ftor), _list.begin(), _list.end()));
_threads.join_all();
}
private:
boost::thread_group _threads;
ftor _ftor;
vector<data> _list;
};
template<typename data>
class Ftor
{
public:
typedef void result_type;
explicit Ftor () {}
result_type operator() (typename vector<data>::iterator &startItr, typename vector<data>::iterator &endItr)
{
for_each(startItr, endItr, cout << bl::_1 << constant("."));
return ;
}
};
However this results in another compile error:
/usr/local/include/boost/lambda/detail/function_adaptors.hpp:45: error: no match for call to ‘(Ftor<int>) (const __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >&, const __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >&)’
ftor.h:41: note: candidates are: void Ftor<data>::operator()(typename std::vector<data, std::allocator<_CharT> >::iterator&, typename std::vector<data, std::allocator<_CharT> >::iterator&) [with data = int]
/usr/local/include/boost/lambda/detail/function_adaptors.hpp:45: error: return-statement with a value, in function returning 'void'
It seems having defined void as a result_type it is now expecting the operator() to return something. I tried returning result_type from within the function but this also generated errors. Any ideas?
Sig (or in your case, simply typedef void result_type; is necessary.
IIRC, lambda::bind makes const copies of its arguments.
There is thus a problem with functors with non-const operator(). This is solved by making Ftor::operator()const or by wrapping (in doFtor()), _ftor with boost::ref
There is a similar problem with the iterators. Wrapping in boost::ref here won't work directly because it would end up using a reference to a temporary. The simpler solution is to modify Ftor::operator() to take its arguments by copy.
The simplest is thus to modify Ftor so that its operator() is const and it takes its arguments by copy:
void operator() (typename vector<data>::iterator startItr, typename vector<data>::iterator endItr)const
If you really can't make Ftor::operator() const, you could modify doFtor() as follows (but it is still necessary to make Ftor::operator() take its arguments by copy):
_threads.create_thread(bind(boost::ref(_ftor), _list.begin(), _list.end()));