Using vector as matrix? - c++

How may I define a vector in C++11 such that its size is 4*5 so I can treat it like a matrix?
(I mean using operator [] like the following)
mat[2][3];
Update:
The following gives me error:
#include <memory>
class Test{
std::vector<int> vect;
};
Error message:
implicit instantiation of undefined template 'std::__1::vector<int, std::__1::allocator<int> >'
std::vector<int> vect;

You just need a nested vector, like this:
auto v = std::vector<std::vector<int>>(4, std::vector<int>(5));
and you can then index it like v[0][0].

The error implicit instantiation of undefined template std::__1::vector ... means std::vector is unknown to the compiler.
You need to #include <vector>

Related

Unordered_map<string, int> works but Unordered_map<string, string> does not

I don't understand why the second block of code in this short example does not compile correctly. It is my understanding that the second parameter in the <> represents the value, which doesn't need to be unique. Why is the second block of code throwing a compiler error, and what do I need to do to remedy it?
// Unordered Map example .cpp
#include <stdio.h>
#include <string>
#include <cstring>
#include <unordered_map>
using namespace std;
int main(void) {
// This works as expected
unordered_map<std::string, int> m;
m["foo"] = 42;
printf("%i\n", m["foo"]);
// This this doesn't compile
unordered_map<std::string, std::string> m1;
m1["foo"] = "42";
printf("%s\n", m1["foo"]);
return 0;
}
I am compiling this code on CentOS 5.8 using
g++44 -c -Wall -std=c++0x -g map_example.cpp
and these are the errors I am getting
map_example.cpp: In function ‘int main()’:
map_example.cpp:20: warning: cannot pass objects of non-POD type ‘struct std::basic_string<char, std::char_traits<char>, std::allocator<char> >’ through ‘...’; call will abort at runtime
map_example.cpp:20: warning: format ‘%s’ expects type ‘char*’, but argument 2 has type ‘int’
If I am having trouble with a basic c++ class such a std:string what do I need to do to have a custom class as a value, where can I find a fully implemented minimal example?
printf does not work with std::string. Either use cout << m1["foo"] or printf("%s", m1["foo"].c_str())
printf("%s\n", m1["foo"]); is C.
For c++ you should use std::cout to have both the string and the int map's values printed out as expected.
The compiler cannot do a translation for a std::string object automatically to const char* (there is no conversion to const char* by default: Why does std::string not provide a conversion to const char*?)

Using an array as a map key is not working with C++ 11 compiler command?

I need to use an array as the map key, but I receive compiler errors indicating that the map declaration does not name a type.
I use the code in a similar question, but the code does not compile even when I have chosen the -std=c++0x or -std=c++11 compiler commands.
The code I used is:
typedef std::array<unsigned int, 3> alphabet;
std::map<alphabet, std::string> dictionary;
dictionary[{{1, 0, 8}}] = "hello";
The error is:
error: 'dictionary' does not name a type| error: expected
unqualified-id before ']' token| ||=== Build finished: 2 errors, 0
warnings (0 minutes, 1 seconds) ===|
I see little on this topic even when searching Google. I am using CodeBlocks as my IDE and chosen the compiler commands mentioned above.
I think the error may be because you're trying to assign to dictionary in file scope. As pointed out, variables should be initialized in global scope, i.e.:
std::map<alphabet, std::string> dictionary = { {{1,0,8}, "hello"} };
Otherwise, you should put it in block scope, i.e. in a main().
#include <array>
#include <map>
typedef std::array<unsigned int, 3> alphabet;
std::map<alphabet, std::string> dictionary;
int main()
{
dictionary[{{1, 0, 8}}] = "hello";
}
As a side note, it seems that the braces can be elided. You do not need two sets of braces. dictionary[{1, 0, 8}] will suffice.
How you compare the arrays for the map sort?
I guess you should supply compare method like this:
struct ltarray
{
bool operator()(const alphabet& s1, const alphabet& s2) const
{
//how you compare???
return (s1<s2);
}
};
and you need to init your map template with the compare method:
std::map<alphabet, std::string, ltarray> dictionary;

Error using unordered_set_of with Boost.Bimap

I'm attempting to follow this example from the documentation (see typedef for word_counter).
#include <string>
#include <boost/bimap.hpp>
#include <boost/bimap/unordered_set_of.hpp>
typedef boost::bimap
<
boost::bimap::unordered_set_of< std::string >,
std::string
> MyBimap;
Error thrown is
test.cpp:11:1: error: wrong number of template arguments (1, should be 5)
In file included from /usr/include/boost/bimap.hpp:13:0, from test.cpp:3:
/usr/include/boost/bimap/bimap.hpp:133:7: error: provided for ‘template class boost::bimaps::bimap’
test.cpp:11:10: error: invalid type in declaration before ‘;’ token
You have a typo.
Instead of
boost::bimap::unordered_set_of< std::string >,
use
boost::bimaps::unordered_set_of< std::string >,
in the template.
It will compile then.

How to declare boost unordered_multimap

I'm trying to use the boost unordered_multimap class and I'm having trouble declaring it. The error follows the code.
#include <iostream>
#include <map> // header file needed for to use MAP STL
#include <boost/unordered_map.hpp>
using namespace std;
int main(void)
{
map<int, map<int, map<int,int> > > _3dstl;
_3dstl[0][0][0] = 10;
cout<<_3d[0][0][0]<<endl;
typedef boost::unordered_multimap<int, typedef boost::unordered_multimap<int, int>> unordered_map;
unordered_map _2d;
return 0;
}
This is the error:
||In function 'int main()':|
|17|error: template argument 2 is invalid|
|17|error: template argument 5 is invalid|
|17|warning: 'typedef' was ignored in this declaration|
|18|error: 'unordered_map' was not declared in this scope|
|18|error: expected ';' before 'location3d'|
||=== Build finished: 4 errors, 1 warnings ===|
Change this line:
typedef boost::unordered_multimap<int, typedef boost::unordered_multimap<int, int>> unordered_map;
To this:
typedef boost::unordered_multimap<int, boost::unordered_multimap<int, int> > unordered_map;
The second typedef is not necessary and a syntax error. Also in C++2003 you have to watch out for >> in template declarations.
Also, please use a different name then unordered_map for the typedef, since this will collide with std::unordered_map if you use using namespace std; (which is IMO a bad practice). A suggestion would be intmap2d or something.

ensure that an iterator dereferences to a certain type

I have to implement a function that takes an iterator. The iterator must dereference to a certain type, say int:
template<typename iter>
void f(iter i) {
// do something here ...
int t = *i;
// do something here ...
}
The problem with this code is that if a user calls the function like this
vector<string> v;
v.push_back("aaa");
f(v.begin());
he will see an error pointing to some place in my code, not in his code (which will be confusing to him). I want the error to be in user's code to ease debugging.
GMan already pointed to a method to solve this via compile time assertions. There is another way to do this, which I prefer (it's my favorite C++ technique). You can put constraints on function arguments in a way that the function is ignored for overload resolution if the constraints don't fit. This is quite terrific, because you can fine tune your function overloads to arbitrary conditions. Here's how:
#include <boost/utility.hpp>
#include <boost/type_traits.hpp>
#include <vector>
template<typename Iter> typename
boost::enable_if<
boost::is_same<typename Iter::value_type,int>,
void>::type
foo(Iter it) { }
int main() {
std::vector<int> v; // this is OK
foo(v.begin());
std::vector<double> v2; // this is an error
foo(v2.begin()); }
If you compile this, you will get
b.cc: In function 'int main()':
b.cc:19:16: error: no matching function for call to 'foo(std::vector<double>::iterator)'
This is because the compiler would consider foo() only, if it's argument has a value_type type inside, which is 'int' (This is what the enable_if part means). The second call of foo() can't satisfy this constraint.
enable_if is mentioned a couple of times in SO, just search for it: https://stackoverflow.com/search?q=enable_if
You could do something like this:
#include <boost/type_traits/is_convertible.hpp>
#include <boost/typeof/typeof.hpp>
#include <boost/mpl/assert.hpp>
template <typename Iter>
void foo(Iter pIter)
{
BOOST_MPL_ASSERT_MSG(
(boost::is_convertible<BOOST_TYPEOF(*pIter), int>::value),
DEREFERENCED_ITERATOR_MUST_BE_CONVERTIBLE_TO_INT,
(int));
// ...
}
#include <vector>
#include <string>
int main(void)
{
std::vector<std::string> v(5);
foo(v.begin());
}
Which makes the message quite visible:
error C2664: 'boost::mpl::assertion_failed' : cannot convert parameter 1 from 'boost::mpl::failed ************(__thiscall foo::DEREFERENCED_ITERATOR_MUST_BE_CONVERTIBLE_TO_INT::* ***********)(int)' to 'boost::mpl::assert::type'
But like James says, most compilers give plenty of information to find out what happened anyway.
Given the code in question, most compilers will refer to the point of instantiation in the diagnostic message. For the following, line 16 is the line f(v.begin());.
Microsoft Visual C++ reports:
> c:\example\main.cpp(16) : see reference to function template instantiation 'void f<std::_Vector_iterator<_Myvec>>(iter)' being compiled
1> with
1> [
1> _Myvec=std::_Vector_val<std::string,std::allocator<std::string>>,
1> iter=std::_Vector_iterator<std::_Vector_val<std::string,std::allocator<std::string>>>
1> ]
g++ reports:
main.cpp:16: instantiated from here
Intel C++ Compiler and Comeau both report:
detected during instantiation of
"void f(iter) [with iter=std::string *]" at line 16
You need to set a constraint on the generic type.