I have this cpp file and I have to write write a header for it, with an own template class. When I try to run the code it throws this 'std::logic_error' what(): basic_string::_M_construct null not valid error. It causes by the map_aligner<std::string, std::string> lsa; line but I don't really understand why and how to solve this issue.
The cpp:
#include <iostream>
#include "mapalign.h"
#include <string>
#include <algorithm>
#include <map>
#include "mapalign.h"
struct string_size_less
{
bool operator()( const std::string& a,
const std::string& b ) const
{
return a.size() < b.size();
}
};
const int max = 1000;
bool check()
{
std::map<std::string, int> sma;
std::map<std::string, int> smb;
std::map<std::string, int> smc;
map_aligner<std::string, int> sa;
sa.add( sma );
sa.add( smb );
sa.add( smc );
sma[ "C++" ] = 1;
smb[ "Ada" ] = 2;
smc[ "C" ] = 3;
smc[ "Python" ] = 4;
smc[ "Ada"] = 5;
sa.align();
std::map<int, double> ima;
std::map<int, double> imb;
for( int i = 0; i < max; ++i )
{
if ( 0 == i % 2 )
{
ima[ i ] = max - i;
}
else
{
imb[ i ] = max;
}
}
map_aligner<int, double> ia;
ia.add( ima );
ia.add( imb );
ia.align();
if ( ( 4 != sma.size() && 1 != imb.count( 0 )) || max * 1U != ima.size() ||
1 != smc.count( "C++" ) || "Ada" != sma.begin()->first ||
0 != sma.begin()->second || 4 != smc.size() ||
1 != smb.count( "Python" ) || 0 != imb.begin()->first ||
0.8 <= imb.begin()->second || 1 != imb.count( max / 2 ) )
{
return false;
}
sma[ "Pascal" ] = 5;
sa.set_filler( max );
sa.align();
std::map<std::string, std::string> langsa;
langsa[ "C++" ] = "<3";
langsa[ "Python" ] = ":|";
std::map<std::string, std::string> langsb;
langsb[ "Brainfuck" ] = ":S";
langsb[ "Python" ] = ":/";
langsb[ "C" ] = ":)";
map_aligner<std::string, std::string> lsa;
lsa.add( langsa );
lsa.add( langsb );
lsa.align();
lsa.erase( "Python" );
if ( 0 != langsa.count( "Python" ) || max != smc[ "Pascal" ] ||
!langsa.begin()->second.empty() || max != smb[ "Pascal" ] ||
2 * 1U != langsb.begin()->second.size() ||
0 != langsb.count( "Python" ) || 1 != langsb.count( "C++" ) )
{
return false;
}
std::map<std::string, std::string, string_size_less> lma;
std::map<std::string, std::string, string_size_less> lmb;
std::map<std::string, std::string, string_size_less> lmc;
lma[ "C++" ] = ":D";
lmb[ "Eiffel" ] = ":P";
lmc[ "C" ] = "8-)";
lmc[ "Ada" ] = "!";
map_aligner<std::string, std::string, string_size_less> ls;
ls.add( lma );
(ls += lmb) += lmc;
ls.align();
std::cout << (3 == ls.count()) << (1 == lmc.count( "Ada" )) <<
(3 * 1U == lmb.size()) << (1 == lma.count( "Python" )) <<
(2 == lsa.count()) << (2 == ia.count()) ;
return ( 3 == ls.count() && 1 == lmc.count( "Ada" ) &&
3 * 1U == lmb.size() && 1 == lma.count( "Python" ) &&
2 == lsa.count() && 2 == ia.count() );
}
int main()
{
std::cout
<< "Your solution is "
<< (check() ? "" : "not ")
<< "ready for submission."
<< std::endl;
}
The h:
#ifndef MAPALIGN_H
#define MAPALIGN_H
#include <vector>
#include <map>
#include <typeinfo>
template<typename KEY, typename VALUE, typename COMPARE = std::less<KEY>>
class map_aligner{
public:
typedef typename std::map<KEY, VALUE, COMPARE>::size_type size_type;
map_aligner() {}
void add(std::map<KEY, VALUE, COMPARE>& m) {
maps_.push_back(&m);
}
map_aligner<KEY, VALUE, COMPARE> operator+=(std::map<KEY, VALUE, COMPARE>& m){
return maps_.push_back(&m);
}
size_type count() const {
return maps_.size();
}
void align(){
for(int i = 0; i != (int)maps_.size(); i++ ){
std::map<KEY, VALUE>* first_map = maps_.at(i);
for(typename std::map<KEY, VALUE>::iterator j = first_map->begin(); j !=first_map->end(); j++ ){
for(int h = 0; h != (int)maps_.size(); h++ ){
std::map<KEY, VALUE>* second_map = maps_.at(h);
if(first_map != second_map && notContainsPair(second_map, j)){
second_map->insert(std::make_pair(j->first, filler_));
}
}
}
}
}
bool notContainsPair(std::map<KEY, VALUE>* map,typename std::map<KEY, VALUE>::iterator it){
for(typename std::map<KEY, VALUE>::iterator g = map->begin(); g != map->end(); g++ ){
if(it->first != g->first){
return true;
}
}
return false;
}
void set_filler(VALUE filler){
filler_ = filler;
}
void erase(KEY key){
for(int h = 0; h != (int)maps_.size(); h++ ){
std::map<KEY, VALUE>* map = maps_.at(h);
typename std::map<KEY, VALUE>::iterator it;
if(typeid(it->first) != typeid(it->first)){
map->erase(key);
}
}
}
private:
std::vector<std::map<KEY, VALUE, COMPARE>*> maps_;
VALUE filler_ = (VALUE) NULL;
};
#endif
That error is caused by you trying to construct a string with a null pointer.
Now look at the code that causes the error
map_aligner<std::string, std::string> lsa;
Both template parameters are strings.
Now look at this code in map_aligner
VALUE filler_ = (VALUE) NULL;
VALUE
is a std::string
so this code is constructing a string from a null pointer, exactly as the error indicates.
I don't know, but I guess you just want this
VALUE filler_ = VALUE();
It's a dangerous thing to try and construct an arbitrary type from NULL
.