I would like to use boost's multi-index container with a class hierarchy. Is this possible?
If I try:
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/identity.hpp>
#include <boost/multi_index/member.hpp>
using namespace ::boost;
using namespace ::boost::multi_index;
class A{
public:
int m;
A(int p = 0){m = p;};
};
class B: public A{
public:
int n;
B(int p = 0, int q = 0): A(p){ n = q;};
};
typedef multi_index_container<
B,
indexed_by<
ordered_unique<identity<B> >,
ordered_non_unique<member<B, int, &B::m> >
>
> mindex;
int main(void){
return 0;
}
I get the following errors:
multiindextest.cpp:25: error: could not convert template argument ‘&A::m’ to ‘int B::*’
multiindextest.cpp:25: error: template argument 1 is invalid
multiindextest.cpp:26: error: template argument 2 is invalid
multiindextest.cpp:27: error: template argument 2 is invalid
multiindextest.cpp:27: error: invalid type in declaration before ‘;’ token
If I change line 25 to:
ordered_non_unique<member<B, int, &B::n> >
It compiles fine. Any help would be much appreciated. Thanks.
I'm not quite sure, if this is what you are looking for, but you can change line 25 to:
ordered_non_unique<member<A, int, &A::m> >
This is compiling on gcc 4.4.
Regards Lars.
Related
#include <map>
#include <memory>
#include <iostream>
using namespace std;
class test
{
public:
test(){}
~test(){}
enum type
{
error = 0
};
private:
shared_ptr<map<int, type>> member_ = make_shared<map<int, type>>();//build error
//shared_ptr<map<type, int>> member_ = make_shared<map<type, int>>();//build ok
};
int main()
{
return 0;
}
when i compile program with "shared_ptr<map<int, type>> member_ = make_shared<map<int, type>>()"
main.cpp:17:63: error: expected ‘;’ at end of member declaration
shared_ptr<map<int, type>> member_ = make_shared<map<int, type>>();
^
main.cpp:17:67: error: expected unqualified-id before ‘>>’ token
shared_ptr<map<int, type>> member_ = make_shared<map<int, type>>();
^
main.cpp:17:58: error: wrong number of template arguments (1, should be at least 2)
shared_ptr<map<int, type>> member_ = make_shared<map<int, type>>();
^
In file included from /usr/include/c++/5/map:61:0,
from main.cpp:1:
/usr/include/c++/5/bits/stl_map.h:96:11: note: provided for ‘template<class _Key, class _Tp, class _Compare, class _Alloc> class std::map’
class map
^
main.cpp:17:42: error: parse error in template argument list
shared_ptr<map<int, type>> member_ = make_shared<map<int, type>>();
^
main.cpp:17:42: error: cannot resolve overloaded function ‘make_shared’ based on conversion to type ‘std::shared_ptr<std::map<int, test::type> >’
Have tried your code with Online C++ Compiler, got the same errors with C++, C++11, and C++14 compatible compilers, but got compiled well with C++17 compatible compiler. This means that your code is not legal in C++ standards prior to C++17. As pointed out by others, the code, however, compiled well on other online compiler sites even with C++11 and C++14 standards. So I would guess the errors are due to supported / unsupported features of compilers.
Well, you are not supposed to initialize class members like this anyway. The initialization of class members should happen in the class constructor, like so:
#include <map>
#include <memory>
#include <iostream>
using namespace std;
class test
{
public:
test() { member_ = make_shared<map<int, type>>(); }
~test() { }
enum type
{
error = 0
};
private:
shared_ptr<map<int, type>> member_;
};
int main()
{
return 0;
}
This compiles fine even in Online C++ Compiler which is the only place we are managing to reproduce the problem.
I want to create a vector of trains, where each train needs a vector of pairs.
If I run the code outside of main(), I get these errors:
naive-bayes.cpp:17:15: error: template argument 1 is invalid
vector<pair> pairs;
naive-bayes.cpp:17:15: error: template argument 2 is invalid
Inside main(), I get these errors:
naive-bayes.cpp:22:15: error: template argument for 'template<class>
class std::allocator' uses local type 'main()::pair'
vector<pair> pairs;
naive-bayes.cpp:22:15: error: trying to instantiate 'template<class> class std::allocator'
naive-bayes.cpp:22:15: error: template argument 2 is invalid
Here is the code:
struct pair {
int index;
int value;
};
struct trains {
string label;
vector<pair> pairs;
};
You're problem is probably due to using namespace std;.
There is a std::pair type in the standard library.
Try this:
#include <string>
#include <vector>
struct pair {
int index;
int value;
};
struct trains {
std::string label;
std::vector<pair> pairs;
};
int main()
{
return 0;
}
Without a full program example to play with, all I can really point out is that your local pair declaration is likely getting confused with std::pair. Change your definition of struct pair to be struct mypair.
I have the following code.
#include <utility>
#include <list>
#include <iostream>
class Pair: public std::pair<unsigned int, unsigned int>{
Pair (unsigned int h, unsigned int l) : pair(h,l){};
};
class PairList: public std::list<Pair>{};
int main(int argc, char** argv){
PairList pl = {{800,400},{800,400}};
}
I compile it using MinGW g++ of v4.6 with the command line
g++ -std=c++0x Test.cpp -o test.exe
and got the error:
error: could not convert '{{800, 400}, {800, 400}}' from '<brace-enclosed initializer list>' to 'PairList'
But if in main() I write
list<pair<unsigned int,unsigned int>> pl = {{800,400},{800,400}};
all works fine.
WTF?
There are two ways:
Don't inherit the from the standard classes, use typedef instead:
typedef std::pair<unsigned int, unsigned int> Pair;
typedef std::list<Pair> PairList;
Implement the correct constructors in your inherited classes (taking std::initializer_list as argument), the base class constructors can't be used automatically.
I recommend the first alternative, as the standard classes (with few exceptions) are not designed to be inherited.
The following header works with the commented part as expected when I call the function bat with no arguments:
class Test
{
public:
void bat(std::vector<int> k = std::vector<int>()) {}
//void cat(std::map<int, std::vector<int> > k = std::map<int, std::vector<int> >()) {}
};
But when I try using the cat function in the header:
class Test
{
public:
void bat(std::vector<int> k = std::vector<int>()) {}
void cat(std::map<int, std::vector<int> > k = std::map<int, std::vector<int> >()) {}
};
I get:
test.h:14: error: expected ',' or '...' before '>' token
test.h:14: error: wrong number of template arguments (1, should be 4)
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_map.h:92: error: provided for 'template<class _Key, class _Tp, class _Compare,\
class _Alloc> class std::map'
test.h:14: error: default argument missing for parameter 2 of 'void Test::cat(std::map<int, std::vector<int, std::allocator<int> >, std::less<int>, std::all\
ocator<std::pair<const int, std::vector<int, std::allocator<int> > > > >, std::vector<int, std::allocator<int> >)'
How come? And are there easy workarounds for this? hopefully not requiring a pointer type change in the interface?
This is my full header:
#ifndef TEST_H
#define TEST_H
#include <map>
#include <vector>
#include <sstream>
#include <iostream>
class Test
{
public:
//void bat(std::vector<int> k = std::vector<int>()) {}
void cat(std::map<int, std::vector<int> > k = std::map<int, std::vector<int> >()) {}
};
#endif
so all the right includes are there. My version of GCC is terribly outdated (well not at home, ill try it at home too) - but at work it's 4.1.2
The code looks OK, but fails on gcc 4.3.4, see here, but compiles fine with 4.6 onwards (I haven't tested 4.4 or 4.5). So it looks like the workaround is to use a newer gcc.
#include <map>
#include <vector>
class Test
{
public:
void bat(std::vector<int> k = std::vector<int>()) {}
void cat(std::map<int, std::vector<int> > k = std::map<int, std::vector<int> >
()) {}
};
int main() {
}
Concerning default parameters, it may be an idea to drop them altogether:
class Test {
public:
void bat(std::vector<int> k) {}
void bat() {}
void cat(std::map<int, std::vector<int> > k) {}
void cat() {}
};
otherwise, you couple the default parameters to the interface, meaning you cannot change them without requiring re-compilation of all client code.
The code you've posted seems fine, so I'm going to turn on my Psychic Debugger module.
Did you:
#include <vector>
...in your header?
From the other posts here, it looks like it could be a compiler problem, in which case, you can get around it by using a typedef instead of the map type directly.
#include <vector>
#include <map>
class Test
{
public:
typedef std::map<int, std::vector<int> > MyMap;
void bat(std::vector<int> k = std::vector<int>()) {}
void cat(MyMap k = MyMap()) {}
};
int main()
{
}
This is C++ core Defect Report 325 http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#325
GCC 4.4 implements the suggested (but not yet official) resolution of the DR, see http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57#c36
class X_class{
public:
struct extra
{int extra1;
int extra2;
int extra3;
};
enum a
{
n,m};
struct x_struct{
char b;
char c;
int d;
int e;
std::map <int, extra> myExtraMap;
};
};
in my code I define :
x_struct myStruct;
why do I get compile errors compiling the above class? The error either says:
1) expected ; before < on the line --- where I defined the map (above) if I eliminate std::
or
2) error: invalid use of ::; error: expected ; before < token
Probably you get erorrs because you didn't #include <map>