Initialization of a templated data member cryptic error - c++

This is my tmp.hpp:
#include <cstdlib>
#include <utility>
#include <unordered_map>
using namespace std;
struct int_int_hasher {
size_t operator()(pair<int, int> const& p) const {
return static_cast<size_t>(p.first) << 32 | p.second;
}
};
template<class T, class H>
class BiBag {
unordered_map<T, uint, H> t_to_id_;
};
And simple tmp.cpp:
#include "tmp.hpp"
class tmp {
BiBag<pair<int, int>, int_int_hasher> tt =
BiBag<std::pair<int, int>, int_int_hasher>();
};
The error message is beyond my understanding:
g++ -std=c++11 -O2 tmp.cpp -lm -o tmp
tmp.cpp:6:32: error: expected ‘;’ at end of member declaration
BiBag<std::pair<int, int>, int_int_hasher>();
^
tmp.cpp:6:32: error: declaration of ‘BiBag<std::pair<int, int>, int_int_hasher> tmp::int_int_hasher’ [-fpermissive]
In file included from tmp.cpp:2:0:
tmp.hpp:7:8: error: changes meaning of ‘int_int_hasher’ from ‘struct int_int_hasher’ [-fpermissive]
struct int_int_hasher {
^
tmp.cpp:6:46: error: expected unqualified-id before ‘>’ token
BiBag<std::pair<int, int>, int_int_hasher>();
^
tmp.cpp:6:16: error: wrong number of template arguments (1, should be 2)
BiBag<std::pair<int, int>, int_int_hasher>();
^
If I remove the hasher from the picture and replace the map with a simple <int,int> map I get no error.
Thank you.

Related

Nested Templates: "expected primary-expression before ')'"

i'm writing a Point class in c++ and use templates for this. But i have a compile error that i don't understand. I wrote a minimal example of the problem:
#include <array>
#include <vector>
#include <iostream>
template <typename T, int DIM>
class Point
{
private:
std::array<T, DIM> values;
public:
template <int ROW>
T get()
{
return values.at(ROW);
};
};
template <typename T>
class Field
{
public:
T print(std::vector<Point<T, 3> >& vec)
{
for (auto it : vec)
{
T bla = it.get<1>(); // the error line 27
}
};
};
int main(int argc,
char* argv[])
{
Point<double, 3> p;
double val = p.get<1>();
std::cout << val << std::endl;
Field<int> f;
std::vector<Point<int, 3> > vec;
f.print(vec);
return 0;
}
I compile with
g++ main2.cpp -std=c++11
and the output is
main2.cpp: In member function ‘T Field<T>::print(std::vector<Point<T, 3> >&)’:
main2.cpp:27:33: error: expected primary-expression before ‘)’ token
T bla = it.get< 1 >();
^
main2.cpp: In instantiation of ‘T Field<T>::print(std::vector<Point<T, 3> >&) [with T = int]’:
main2.cpp:41:16: required from here
main2.cpp:27:27: error: invalid operands of types ‘<unresolved overloaded function type>’ and ‘int’ to binary ‘operator<’
T bla = it.get< 1 >();
Does someone know why the error occurs and how to solve it?
Thank you.
Since it.get<1>() is dependent on a template parameter, you need to tell the compiler that get is a template so that it can be parsed correctly:
T bla = it.template get<1>();
Additionally, you don't return anything from that print function, even though the declaration says it should return a T.
See this question for more detail about the template keyword in this context.
Change the line
T bla = it.get<1>(); // the error line 27
to:
T bla = it.template get<1>(); // the error line 27
You need the template keyword to access template member functions if the class they're in is itself a template class.

compilation error whith boost-python and lapack

I created a program using boost for extracting python variables and lapack for solving matrix. However I have some trouble in compilation process
Here are my includes and the firsts line of code :
#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
#include "lapacke.h"
#include <math.h>
#include <omp.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <stdarg.h>
#include <math.h>
#include <sys/times.h>
#include <exception>
#include <fstream>
#include <iostream>
#include <cassert>
#include <algorithm>
#include <string>
#include <sstream>
#include <vector>
#include <map>
#include <list>
#include <set>
#include <limits>
#include <Python.h>
#include <arrayobject.h>
#include <boost/timer/timer.hpp>
#include <boost/python.hpp>
#include "boost/python/extract.hpp"
using namespace std;
The compilation results in a large amount of errors that I have difficulties to interpret this output.
Here is a sample :
In file included from /usr/include/c++/4.9/complex.h:36:0,
from /usr/include/lapacke.h:73,
from /project/git/CLCCD/whittaker/wfilter.cpp:4:
/usr/include/boost/operators.hpp:308:26: error: expected identifier before ‘(’ token
template <class T, class I, class R, class B = ::boost::detail::empty_base<T> >
^
/usr/include/boost/operators.hpp:308:26: error: expected ‘)’ before ‘__extension__’
template <class T, class I, class R, class B = ::boost::detail::empty_base<T> >
^
/usr/include/boost/operators.hpp:308:26: error: expected ‘>’ before ‘__extension__’
/usr/include/boost/operators.hpp:308:26: error: expected unqualified-id before ‘)’ token
template <class T, class I, class R, class B = ::boost::detail::empty_base<T> >
^
In file included from /usr/include/boost/system/error_code.hpp:17:0,
from /usr/include/boost/chrono/detail/system.hpp:12,
from /usr/include/boost/chrono/system_clocks.hpp:64,
from /usr/include/boost/chrono/chrono.hpp:13,
from /usr/include/boost/timer/timer.hpp:14,
from /project/git/CLCCD/whittaker/wfilter.cpp:37:
/usr/include/boost/operators.hpp:649:7: error: ‘indexable’ was not declared in this scope
, indexable<T, D, R, B
^
/usr/include/boost/operators.hpp:650:7: error: wrong number of template arguments (6, should be 3)
> > > > {};
^
/usr/include/boost/operators.hpp:420:8: error: provided for ‘template<class T, class U, class B> struct boost::additive2’
struct additive2
^
/usr/include/boost/operators.hpp:650:9: error: template argument 2 is invalid
> > > > {};
^
/usr/include/boost/operators.hpp:650:11: error: template argument 3 is invalid
> > > > {};
^
/usr/include/boost/operators.hpp:650:13: error: expected ‘{’ before ‘>’ token
> > > > {};
^
/usr/include/boost/operators.hpp:650:13: error: expected unqualified-id before ‘>’ token
/usr/include/boost/operators.hpp:851:1: error: ‘indexable’ is not a member of ‘boost’
BOOST_OPERATOR_TEMPLATE3(indexable)
^
/usr/include/boost/operators.hpp:851:1: error: ‘indexable’ is not a member of ‘boost’
/usr/include/boost/operators.hpp:851:1: error: wrong number of template arguments (4, should be 1)
BOOST_OPERATOR_TEMPLATE3(indexable)
^
/usr/include/boost/operators.hpp:731:26: error: provided for ‘template<class T> struct boost::is_chained_base’
template<class T> struct is_chained_base {
^
/usr/include/boost/operators.hpp:851:1: error: expected unqualified-id before ‘>’ token
BOOST_OPERATOR_TEMPLATE3(indexable)
^
In file included from /usr/include/c++/4.9/complex.h:36:0,
from /usr/include/lapacke.h:73,
from /project/git/CLCCD/whittaker/wfilter.cpp:4:
/usr/include/boost/smart_ptr/detail/spinlock_pool.hpp:34:15: error: expected ‘)’ before ‘__extension__’
template< int I > class spinlock_pool
^
/usr/include/boost/smart_ptr/detail/spinlock_pool.hpp:34:15: error: expected ‘>’ before ‘__extension__’
/usr/include/boost/smart_ptr/detail/spinlock_pool.hpp:34:15: error: expected unqualified-id before ‘)’ token
template< int I > class spinlock_pool
^
/usr/include/boost/smart_ptr/detail/spinlock_pool.hpp:75:15: error: expected ‘)’ before ‘__extension__’
template< int I > spinlock spinlock_pool< I >::pool_[ 41 ] =
^
/usr/include/boost/smart_ptr/detail/spinlock_pool.hpp:75:15: error: expected ‘>’ before ‘__extension__’
/usr/include/boost/smart_ptr/detail/spinlock_pool.hpp:75:15: error: expected unqualified-id before ‘)’ token
template< int I > spinlock spinlock_pool< I >::pool_[ 41 ] =
^
// some other lines ...
In file included from /usr/include/boost/shared_ptr.hpp:17:0,
from /usr/include/boost/python/converter/shared_ptr_to_python.hpp:10,
from /usr/include/boost/python/converter/arg_to_python.hpp:15,
from /usr/include/boost/python/call.hpp:15,
from /usr/include/boost/python/object_core.hpp:14,
from /usr/include/boost/python/args.hpp:25,
from /usr/include/boost/python.hpp:11,
from /project/git/CLCCD/whittaker/wfilter.cpp:38:
/usr/include/boost/smart_ptr/shared_ptr.hpp: In function ‘boost::shared_ptr<T> boost::atomic_load(const boost::shared_ptr<T>*)’:
/usr/include/boost/smart_ptr/shared_ptr.hpp:954:5: error: ‘spinlock_pool’ is not a member of ‘boost::detail’
boost::detail::spinlock_pool<2>::scoped_lock lock( p );
^
/usr/include/boost/smart_ptr/shared_ptr.hpp:954:36: error: ‘::scoped_lock’ has not been declared
boost::detail::spinlock_pool<2>::scoped_lock lock( p );
^
/usr/include/boost/smart_ptr/shared_ptr.hpp: In function ‘void boost::atomic_store(boost::shared_ptr<T>*, boost::shared_ptr<T>)’:
/usr/include/boost/smart_ptr/shared_ptr.hpp:965:5: error: ‘spinlock_pool’ is not a member of ‘boost::detail’
boost::detail::spinlock_pool<2>::scoped_lock lock( p );
^
/usr/include/boost/smart_ptr/shared_ptr.hpp:965:36: error: ‘::scoped_lock’ has not been declared
boost::detail::spinlock_pool<2>::scoped_lock lock( p );
^
// and it continues...
Q : My limited knowledge on compilation tends to suppose a conflict between lapack and boost, but how to resolve ?
Q : Is this a problem related to any namespace defined in cpp file ?
In fact this was a problem in includes order...
by putting #include "lapacke.h" after boost includes, it solved the things...
I'm having other problems now... but that's another story...

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);
}

In-class initialization of std::map

I have this snippet of C++ code that doesn't compile under g++-4.9.1 (I used the command "g++ -c --std=c++11 map.cc")
#include <map>
#include <cstdint>
class A {
std::map<uint8_t, uint8_t> b = std::map<uint8_t, uint8_t>();
};
I get the following error when compiling:
map.cc:5:52: error: expected ‘;’ at end of member declaration
std::map<uint8_t, uint8_t> b = std::map<uint8_t, uint8_t>();
^
map.cc:5:52: error: declaration of ‘std::map<unsigned char, unsigned char> A::uint8_t’ [-fpermissive]
In file included from /usr/lib/gcc/x86_64-linux-gnu/4.9/include/stdint.h:9:0,
from /usr/include/c++/4.9/cstdint:41,
from /usr/include/c++/4.9/bits/char_traits.h:380,
from /usr/include/c++/4.9/string:40,
from /usr/include/c++/4.9/stdexcept:39,
from /usr/include/c++/4.9/array:38,
from /usr/include/c++/4.9/tuple:39,
from /usr/include/c++/4.9/bits/stl_map.h:63,
from /usr/include/c++/4.9/map:61,
from map.cc:1:
/usr/include/stdint.h:48:24: error: changes meaning of ‘uint8_t’ from ‘typedef unsigned char uint8_t’ [-fpermissive]
typedef unsigned char uint8_t;
^
map.cc:5:59: error: expected unqualified-id before ‘>’ token
std::map<uint8_t, uint8_t> b = std::map<uint8_t, uint8_t>();
^
map.cc:5:43: error: wrong number of template arguments (1, should be 4)
std::map<uint8_t, uint8_t> b = std::map<uint8_t, uint8_t>();
^
In file included from /usr/include/c++/4.9/map:61:0,
from map.cc:1:
/usr/include/c++/4.9/bits/stl_map.h:96:11: error: provided for ‘template<class _Key, class _Tp, class _Compare, class _Alloc> class std::map’
class map
^
However, if I replace uint8_t with int, it compiles fine.
The problem with g++ is much larger, whenever you use a template as a class member, you cannot use member initialization if any parameter (except the first one), is a typedef or in another namespace.
typedef int I;
template<typename T1, typename T2> struct A {};
struct B {
A<I,float> a1=A<I,float>(); // works!
A<float,I> a2=A<float,I>(); // does not compile!
// This is the same reason the map does not comile, as string is a typedef
};
FWIW, if you need a work around, the following works:
class A {
typedef std::map<uint8_t, uint8_t> B;
B b = B();
};

unordered key_type for non library types requires hash<> specialization?

I'm trying to create an std::unordered_map with xercesc::XMLUri as the key type.
#include <unordered_map>
#include "xercesc/util/XMLUri.hpp"
int main()
{
std::unordered_map<xercesc::XMLUri,xercesc::XMLUri> uriMap;
}
resulting in the following :
clang++ -std=c++11 -O0 -emit-llvm -g3 -Wall -c -fmessage-length=0 -I/usr/include ../xx.cpp
In file included from ../xx.cpp:1:
In file included from /usr/bin/../lib/gcc/i686-linux-gnu/4.7/../../../../include/c++/4.7/unordered_map:43:
/usr/bin/../lib/gcc/i686-linux-gnu/4.7/../../../../include/c++/4.7/bits/functional_hash.h:59:7: error: static_assert failed "std::hash is not specialized for this type"
static_assert(sizeof(_Tp) < 0,
^ ~~~~~~~~~~~~~~~
/usr/bin/../lib/gcc/i686-linux-gnu/4.7/../../../../include/c++/4.7/bits/unordered_map.h:45:32: note: in instantiation of template class 'std::hash<xercesc_3_1::XMLUri>' requested here
integral_constant<bool, !__is_final(_Hash)>,
^
/usr/bin/../lib/gcc/i686-linux-gnu/4.7/../../../../include/c++/4.7/bits/unordered_map.h:263:14: note: in instantiation of default argument for '__unordered_map<xercesc_3_1::XMLUri, xercesc_3_1::XMLUri, std::hash<xercesc_3_1::XMLUri>, std::equal_to<xercesc_3_1::XMLUri>, std::allocator<std::pair<const xercesc_3_1::XMLUri, xercesc_3_1::XMLUri> > >' required here
: public __unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../xx.cpp:6:54: note: in instantiation of template class 'std::unordered_map<xercesc_3_1::XMLUri, xercesc_3_1::XMLUri, std::hash<xercesc_3_1::XMLUri>, std::equal_to<xercesc_3_1::XMLUri>, std::allocator<std::pair<const xercesc_3_1::XMLUri, xercesc_3_1::XMLUri> > >' requested here
std::unordered_map<xercesc::XMLUri,xercesc::XMLUri> uriMap;
I know the unordered containers in C++0x only supply hash<> specializations for some of the library types. How do I create the required hash<xercesc::XMLUri> specialization for xercesc::XMLUri?
EDIT: I came up with this. Does it seem reasonable?
#include "xercesc\util\XMLUri.hpp"
#include <string>
namespace std
{
size_t hash<xercesc::XMLUri>::operator()(const xercesc::XMLUri& uri) const
{
return hash<std::wstring>()(uri.getUriText());
}
}
Almost. It should be like this (thanks to #jogojapan for pointing out the missing typedefs!):
#include <string>
#include <functional>
namespace std
{
template <> struct hash<xercesc::XMLUri>
{
typedef size_t result_type;
typedef xercesc::XMLUri argument_type;
size_t operator()(xercesc::XMLUri const & uri) const noexcept
{
return hash<wstring>()(uri.getUriText());
}
};
}
std::hash is a struct, you must specialize the whole struct, not just the function, then your way of specializing a template is wrong too:
namespace std
{
template <>
struct hash<xercesc::XMLUri>
{
size_t operator()(const xercesc::XMLUri& uri) const
{
return hash<std::wstring>()(uri.getUriText());
}
};
}