I'm having some issues regarding a segment fault
Program received signal SIGSEGV, Segmentation fault.
0x0000000000403a62 in std::_Deque_iterator<float, float&, float*>::_Deque_iterator (this=0x7fffffffc5c0, __x=...)
at /usr/include/c++/4.6/bits/stl_deque.h:136
136 _M_last(__x._M_last), _M_node(__x._M_node) { }
(gdb) up
#1 0x0000000000403a0f in std::deque<float, std::allocator<float> >::begin (this=0x64) at /usr/include/c++/4.6/bits/stl_deque.h:1010
1010 { return this->_M_impl._M_start; }
(gdb) up
#2 0x000000000040326f in std::deque<float, std::allocator<float> >::front (this=0x64) at /usr/include/c++/4.6/bits/stl_deque.h:1286
1286 { return *begin(); }
(gdb) up
#3 0x000000000040248c in std::queue<float, std::deque<float, std::allocator<float> > >::front (this=0x64)
at /usr/include/c++/4.6/bits/stl_queue.h:165
165 return c.front();
(gdb) up
#4 0x0000000000402ee3 in KDTree::Node::Create (this=0x6251c0, coords=0x623ec0, limit=500) at KDTree.hxx:64
64 if( ( *itC ) -> front() > maxAbove ) maxAbove = ( *itC ) -> front();
Here's the piece of code
template< class T, class D >
void KDTree< T, D >::Node::
Create( Coords* coords, D limit )
{
Coords* newCoordsBelowMedian = new Coords();
Coords* newCoordsAboveMedian = new Coords();
D maxAbove = 0,
minAbove = 0,
maxBelow = 0,
minBelow = 0;
this -> m_Coords = coords;
this -> m_Median = GetMedian( *coords );
typename Coords :: iterator itC = this -> m_Coords -> begin( );
//Change of coordinates for next iteration
for( ; itC != this -> m_Coords -> end( ); itC++ )
{
Dims* newDim = *itC;
D value = newDim -> front( );
newDim -> pop( );
newDim -> push( value );
if( newDim -> front() >= this -> m_Median ) newCoordsAboveMedian -> insert( );
else newCoordsBelowMedian -> insert( );
}
typename Coords :: iterator itCA = newCoordsAboveMedian -> begin( );
typename Coords :: iterator itCB = newCoordsBelowMedian -> begin( );
minBelow = std::numeric_limits<D>::max();
minAbove = std::numeric_limits<D>::max();
//Max radius
for( ; itC != newCoordsAboveMedian -> end( ); itCA++ )
{
if( ( *itC ) -> front() > maxAbove ) maxAbove = ( *itC ) -> front();
if( ( *itC ) -> front() < minAbove ) minAbove = ( *itC ) -> front();
}
for( ; itC != newCoordsBelowMedian -> end( ); itCB++ )
{
if( ( *itC ) -> front() > maxBelow ) maxBelow = ( *itC ) -> front();
if( ( *itC ) -> front() > maxBelow ) minBelow = ( *itC ) -> front();
}
if( abs( maxAbove - minAbove ) < limit && newCoordsAboveMedian -> size() > 0 )
{
this -> m_R = new Node();
this -> m_R -> Create( newCoordsAboveMedian, limit );
}
if( abs( maxBelow - minBelow ) < limit && newCoordsAboveMedian -> size() > 0 )
{
this -> m_L = new Node();
this -> m_L -> Create( newCoordsBelowMedian, limit );
}
}
I suspect is because pointers at the first for are being lost upon completion, however, I don't know any solution to this issue, any thoughts?
It seems itC is an iterator for this -> m_Coords which got run to the end in the first loop. The same iterator is used to control the later loops. Did you mean this loop
for( ; itC != newCoordsAboveMedian -> end( ); itCA++ )
{
if( ( *itC ) -> front() > maxAbove ) maxAbove = ( *itC ) -> front();
if( ( *itC ) -> front() < minAbove ) minAbove = ( *itC ) -> front();
}
To read
for( ; itCA != newCoordsAboveMedian -> end( ); itCA++ )
{
if( ( *itCA ) -> front() > maxAbove ) maxAbove = ( *itCA ) -> front();
if( ( *itCA ) -> front() < minAbove ) minAbove = ( *itCA ) -> front();
}
... or, what I would do if I were to write this loop:
for (typename Coords::iterator it = newCoordsAboveMedian->begin( ),
end = newCoordsAboveMedian->end();
it != end; ++it) {
if( ( *it ) -> front() > maxAbove ) maxAbove = ( *it ) -> front();
if( ( *it ) -> front() < minAbove ) minAbove = ( *it ) -> front();
}
(likewise for the other loop).
Related
I'm trying to write an STL like container for BST. I have two different functions to insert lvalue and rvalue. Function with rvalue overwrites the all the previous inserted values.
Here is the code:
std::pair<iterator, bool> insert( value_type&& value ) {
return insert_unique( std::move( value ) );
}
template<typename Vp_> std::pair<iterator, bool> insert_unique( Vp_&& value ) {
node_holder_ h_ = make_node_holder( std::move( value ) );
node_pointer_ root_ = ( *header_ ).parent_;
node_pointer_ inserted_node = h_.release();
if ( root_ == nullptr ) {
( *header_ ).parent_ = inserted_node;
( *header_ ).left_ = inserted_node;
( *header_ ).right_ = inserted_node;
inserted_node->parent_ = header_;
size_++;
return std::make_pair( make_iterator( inserted_node ), true );
}
node_pointer_ parent = root_;
node_pointer_ x = root_;
while ( x != nullptr ) {
parent = x;
if ( compare_( inserted_node->key_, x->key_ ) )
x = x->left_;
else if ( compare_( x->key_, inserted_node->key_ ) )
x = x->right_;
else
return std::make_pair( make_iterator( x ), false );
}
if ( compare_( inserted_node->key_, parent->key_ ) )
parent->left_ = inserted_node;
else
parent->right_ = inserted_node;
inserted_node->parent_ = parent;
// Update leftmost and right most
if ( compare_( inserted_node->key_, leftmost()->key_ ) ) ( *header_ ).left_ = inserted_node;
if ( !( compare_( inserted_node->key_, rightmost()->key_ ) ) &&
!( compare_( rightmost()->key_, inserted_node->key_ ) ) ) {
( *header_ ).right_ = inserted_node;
inserted_node->right_ = header_;
}
size_++;
return std::make_pair( make_iterator( inserted_node ), true );
}
node_holder_ make_node_holder( value_type&& value ) {
// std::cout << "args holders " << std::endl;
node_allocator_& na_ = get_allocator();
node_holder_ nh_( na_.allocate( 1 ), node_destructor_( na_ ) );
node_traits_::construct( na_, nh_.get(), std::move( value ) );
nh_.get_deleter().value_constructed_ = true;
return std::move( nh_ );
}
I referred to the talk by Scott-Meyers and cascaded the rvalue by using std::move. But, there is some error in the code which is causing the overwrite. Can you please share if you are able to identify the error causing this issue?
Code repository. The bst.h class is in lib/ directory.
Please share if you have any other comments and feedback on the code.
I am trying to edit my hash table to form a double hashing class but can't seem to get it right.
I was wondering if anyone had any insight. I was told that all I needed to do was edit the findPos() where I now have to provide new probes using a new strategy.
**I did some research and it says in double probing you would use R-(x mod R) where R >size and a prime smaller than the table size. So do I make a new rehash function?
here is my code:
template <typename HashedObj>
class HashTable
{
public:
explicit HashTable( int size = 101 ) : array( nextPrime( size ) )
{ makeEmpty( ); }
bool contains( const HashedObj & x ) const
{
return isActive( findPos( x ) );
}
void makeEmpty( )
{
currentSize = 0;
for( auto & entry : array )
entry.info = EMPTY;
}
bool insert( const HashedObj & x )
{
// Insert x as active
int currentPos = findPos( x );
if( isActive( currentPos ) )
return false;
if( array[ currentPos ].info != DELETED )
++currentSize;
array[ currentPos ].element = x;
array[ currentPos ].info = ACTIVE;
// Rehash;
if( currentSize > array.size( ) / 2 )
rehash( );
return true;
}
bool insert( HashedObj && x )
{
// Insert x as active
int currentPos = findPos( x );
if( isActive( currentPos ) )
return false;
if( array[ currentPos ].info != DELETED )
++currentSize;
array[ currentPos ] = std::move( x );
array[ currentPos ].info = ACTIVE;
// Rehash; see Section 5.5
if( currentSize > array.size( ) / 2 )
rehash( );
return true;
}
bool remove( const HashedObj & x )
{
int currentPos = findPos( x );
if( !isActive( currentPos ) )
return false;
array[ currentPos ].info = DELETED;
return true;
}
enum EntryType { ACTIVE, EMPTY, DELETED };
private:
struct HashEntry
{
HashedObj element;
EntryType info;
HashEntry( const HashedObj & e = HashedObj{ }, EntryType i = EMPTY )
: element{ e }, info{ i } { }
HashEntry( HashedObj && e, EntryType i = EMPTY )
: element{ std::move( e ) }, info{ i } { }
};
vector<HashEntry> array;
int currentSize;
bool isActive( int currentPos ) const
{ return array[ currentPos ].info == ACTIVE; }
int findPos( const HashedObj & x ) const
{
int offset = 1;
int currentPos = myhash( x );
while( array[ currentPos ].info != EMPTY &&
array[ currentPos ].element != x )
{
currentPos += offset; // Compute ith probe
offset += 2;
if( currentPos >= array.size( ) )
currentPos -= array.size( );
}
return currentPos;
}
void rehash( )
{
vector<HashEntry> oldArray = array;
// Create new double-sized, empty table
array.resize( nextPrime( 2 * oldArray.size( ) ) );
for( auto & entry : array )
entry.info = EMPTY;
// Copy table over
currentSize = 0;
for( auto & entry : oldArray )
if( entry.info == ACTIVE )
insert( std::move( entry.element ) );
}
size_t myhash( const HashedObj & x ) const
{
static hash<HashedObj> hf;
return hf( x ) % array.size( );
}
};
I am not sure of understanding your code, but let me pose some observations that they should not be considered as an answer, but their size is greater that what is allowed to comment.
If you use quadratic probing, then I think in the method findPos() you should advance currentPos in some as currentPos*currentPos % array.size(). Currently, as I see, you increase currentPos in one unity (offset is initially 1), after 2 unities, after 4 and so on
Probably you are trying a fast way for compute the quadratic probe. If this is the case, then offset should not be increased by two, but multiplied by two. That would be some as offset *= 2, but because you should count the number of collisions you should increase offset.
Maybe a simpler way would be:
currentPos += 2*offset++ - 1; // fast way of doing quadratic resolution
Your resizing is ok, given that it guarantees that the table will be at least half empty and consequently the search of availables entries when the insertion is executed is guaranteed.
Good luck
It appears that you want to implement double hashing for probing. This is a technique for resolving collisions by using a second hash of the input key. In the original quadratic function, you continually add an increasing offset to the index value until you find an empty spot in the hash table. The only important difference in a double hashing function would be the value of the offset.
If I were you, I would create a new hash function which is similar to the first one, but I would replace the return statement with return R - ( hf(x) % R ); for a provided R value. Then I would change findPos to set offset equal to this second hash function (Also remember to remove the offset += 2; line because the offset is no longer increasing).
This code
table_edges[ this_relationship ] = boost::add_edge(
table_vertices[ string( foreign_keys[i]["parent_table"].c_str() ) ],
table_vertices[ string( foreign_keys[i]["child_table"].c_str() ) ],
this_relationship,
rg
).first;
ds.union_set(
table_vertices[ string( foreign_keys[i]["parent_table"].c_str() ) ],
table_vertices[ string( foreign_keys[i]["child_table"].c_str() ) ]
);
gives this error and many others regarding get
/usr/include/boost/pending/detail/disjoint_sets.hpp:59:33: error: no matching function for call to ‘get(long unsigned int*&, long unsigned int&)’
I am using bundled properties.
typedef boost::adjacency_list <
boost::vecS,
boost::vecS,
boost::undirectedS,
string,
foreign_key_relationship
> relational_graph;
The rank & parent typedefs are declared globally.
How can this error be resolved?
struct foreign_key_relationship{
string parent_table;
string parent_column;
string child_table;
string child_column;
foreign_key_relationship(){}
foreign_key_relationship( string pt, string pc, string ct, string cc ) : parent_table( pt ), parent_column( pc ), child_table( ct ), child_column( cc ) {}
};
inline bool operator==(const foreign_key_relationship& lhs, const foreign_key_relationship& rhs)
{
return
lhs.parent_table == rhs.parent_table
&& lhs.parent_column == rhs.parent_column
&& lhs.child_table == rhs.child_table
&& lhs.child_column == rhs.child_column
;
}
inline bool operator<(const foreign_key_relationship& lhs, const foreign_key_relationship& rhs)
{
return
lhs.parent_table < rhs.parent_table
&& lhs.parent_column < rhs.parent_column
&& lhs.child_table < rhs.child_table
&& lhs.child_column < rhs.child_column
;
}
typedef boost::adjacency_list < boost::vecS, boost::vecS, boost::undirectedS, string, foreign_key_relationship > relational_graph;
typedef boost::graph_traits<relational_graph>::vertex_descriptor relational_vertex;
typedef boost::graph_traits<relational_graph>::vertices_size_type relational_vertex_index;
typedef boost::graph_traits<relational_graph>::edge_descriptor relational_edge;
typedef relational_vertex_index* relational_rank;
typedef relational_vertex* relational_parent;
void libpqxx_error( const pqxx_exception &e ){
cerr << "*** Caught pqxx_exception:\n";
cerr << e.base().what() << "\n";
const sql_error *s=dynamic_cast<const sql_error*>(&e.base());
if (s) std::cerr << "Query was: " << s->query() << "\n";
}
void connect_relational_vertices( map< foreign_key_relationship, relational_edge > &table_edges, result &foreign_keys, set<string> &tables_to_connect, map< string, relational_vertex > &table_vertices, relational_graph &rg, boost::disjoint_sets<relational_rank, relational_parent> &ds ){
for( unsigned i=0; i<foreign_keys.size(); i++ ){
foreign_key_relationship this_relationship(
foreign_keys[i]["parent_table"].c_str(),
foreign_keys[i]["parent_column"].c_str(),
foreign_keys[i]["child_table"].c_str(),
foreign_keys[i]["child_column"].c_str()
);
if( !table_edges.count( this_relationship ) && tables_to_connect.count( foreign_keys[i]["parent_table"].c_str() ) && tables_to_connect.count( foreign_keys[i]["child_table"].c_str() ) ){
table_edges[ this_relationship ] = boost::add_edge(
table_vertices[ string( foreign_keys[i]["parent_table"].c_str() ) ],
table_vertices[ string( foreign_keys[i]["child_table"].c_str() ) ],
this_relationship,
rg
).first;
ds.union_set( table_vertices[ string( foreign_keys[i]["parent_table"].c_str() ) ], table_vertices[ string( foreign_keys[i]["child_table"].c_str() ) ] );
}
}
}
void add_possible_linking_vertex( result &foreign_keys, map< string, relational_vertex > &table_vertices, relational_graph &rg ){
for( unsigned i=0; i<foreign_keys.size(); i++ ){
if( !table_vertices.count( foreign_keys[i]["parent_table"].c_str() ) ){
table_vertices[ foreign_keys[i]["parent_table"].c_str() ] = boost::add_vertex( foreign_keys[i]["parent_table"].c_str(), rg );
break;
}
if( foreign_keys[i]["child_table"].c_str() ){
table_vertices[ foreign_keys[i]["child_table"].c_str() ] = boost::add_vertex( foreign_keys[i]["child_table"].c_str(), rg );
break;
}
}
}
set< foreign_key_relationship > get_foreign_keys( transaction_base &t, set<string> tables_to_connect ){
try{
result foreign_keys = t.prepared("get_foreign_keys").exec();
set< foreign_key_relationship > relational_routes;
if( tables_to_connect.size() ){
relational_graph rg;
map< string, relational_vertex > table_vertices;
for( string table: tables_to_connect )
table_vertices[ table ] = boost::add_vertex( table, rg );
std::vector<relational_vertex_index> rank( num_vertices(rg) );
std::vector<relational_vertex> parent( num_vertices(rg) );
boost::disjoint_sets<relational_rank, relational_parent> ds(&rank[0], &parent[0]);
boost::initialize_incremental_components(rg, ds);
boost::incremental_components(rg, ds);
map< foreign_key_relationship, relational_edge > table_edges;
for( unsigned i=0; i<foreign_keys.size(); i++ )
connect_relational_vertices( table_edges, foreign_keys, tables_to_connect, table_vertices, rg, ds );
}
return relational_routes;
}
catch( const pqxx_exception &e ){
libpqxx_error( e );
set< foreign_key_relationship > relational_routes;
return relational_routes;
}
}
I am using libpqxx, and the query to find all foreign key relationships is here.
I have just spent ~15 minute to add the missing bits to the sample code. I was gonna edit the question and leave a comment, "sadly I ran out of time to look at your actual question".
However, then it struck me that the actual question was "why does it not compile"?
Well then, it compiles for me, so maybe this will help you figure out what's different none-the-less?
#include <boost/graph/use_mpi.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/distributed/dehne_gotz_min_spanning_tree.hpp>
#include <boost/graph/incremental_components.hpp>
#include <iostream>
#include <pqxx/except.hxx>
#include <pqxx/transaction_base.hxx>
#include <set>
#include <map>
#include <string>
using std::string;
using std::set;
using std::map;
using namespace pqxx;
struct foreign_key_relationship{
string parent_table;
string parent_column;
string child_table;
string child_column;
foreign_key_relationship(){}
foreign_key_relationship( string pt, string pc, string ct, string cc ) : parent_table( pt ), parent_column( pc ), child_table( ct ), child_column( cc ) {}
};
inline bool operator==(const foreign_key_relationship& lhs, const foreign_key_relationship& rhs)
{
return
lhs.parent_table == rhs.parent_table
&& lhs.parent_column == rhs.parent_column
&& lhs.child_table == rhs.child_table
&& lhs.child_column == rhs.child_column
;
}
inline bool operator<(const foreign_key_relationship& lhs, const foreign_key_relationship& rhs)
{
return
lhs.parent_table < rhs.parent_table
&& lhs.parent_column < rhs.parent_column
&& lhs.child_table < rhs.child_table
&& lhs.child_column < rhs.child_column
;
}
typedef boost::adjacency_list < boost::vecS, boost::vecS, boost::undirectedS, string, foreign_key_relationship > relational_graph;
typedef boost::graph_traits<relational_graph>::vertex_descriptor relational_vertex;
typedef boost::graph_traits<relational_graph>::vertices_size_type relational_vertex_index;
typedef boost::graph_traits<relational_graph>::edge_descriptor relational_edge;
typedef relational_vertex_index* relational_rank;
typedef relational_vertex* relational_parent;
void libpqxx_error( const pqxx_exception &e ){
std::cerr << "*** Caught pqxx_exception:\n";
std::cerr << e.base().what() << "\n";
const sql_error *s=dynamic_cast<const sql_error*>(&e.base());
if (s) std::cerr << "Query was: " << s->query() << "\n";
}
void connect_relational_vertices( map< foreign_key_relationship, relational_edge > &table_edges, result &foreign_keys, set<string> &tables_to_connect, map< string, relational_vertex > &table_vertices, relational_graph &rg, boost::disjoint_sets<relational_rank, relational_parent> &ds ){
for( unsigned i=0; i<foreign_keys.size(); i++ ){
foreign_key_relationship this_relationship(
foreign_keys[i]["parent_table"].c_str(),
foreign_keys[i]["parent_column"].c_str(),
foreign_keys[i]["child_table"].c_str(),
foreign_keys[i]["child_column"].c_str()
);
if( !table_edges.count( this_relationship ) && tables_to_connect.count( foreign_keys[i]["parent_table"].c_str() ) && tables_to_connect.count( foreign_keys[i]["child_table"].c_str() ) ){
table_edges[ this_relationship ] = boost::add_edge(
table_vertices[ string( foreign_keys[i]["parent_table"].c_str() ) ],
table_vertices[ string( foreign_keys[i]["child_table"].c_str() ) ],
this_relationship,
rg
).first;
ds.union_set( table_vertices[ string( foreign_keys[i]["parent_table"].c_str() ) ], table_vertices[ string( foreign_keys[i]["child_table"].c_str() ) ] );
}
}
}
void add_possible_linking_vertex( result &foreign_keys, map< string, relational_vertex > &table_vertices, relational_graph &rg ){
for( unsigned i=0; i<foreign_keys.size(); i++ ){
if( !table_vertices.count( foreign_keys[i]["parent_table"].c_str() ) ){
table_vertices[ foreign_keys[i]["parent_table"].c_str() ] = boost::add_vertex( foreign_keys[i]["parent_table"].c_str(), rg );
break;
}
if( foreign_keys[i]["child_table"].c_str() ){
table_vertices[ foreign_keys[i]["child_table"].c_str() ] = boost::add_vertex( foreign_keys[i]["child_table"].c_str(), rg );
break;
}
}
}
set< foreign_key_relationship > get_foreign_keys( transaction_base &t, set<string> tables_to_connect ){
try{
result foreign_keys = t.prepared("get_foreign_keys").exec();
set< foreign_key_relationship > relational_routes;
if( tables_to_connect.size() ){
relational_graph rg;
map< string, relational_vertex > table_vertices;
for( string table: tables_to_connect )
table_vertices[ table ] = boost::add_vertex( table, rg );
std::vector<relational_vertex_index> rank( num_vertices(rg) );
std::vector<relational_vertex> parent( num_vertices(rg) );
boost::disjoint_sets<relational_rank, relational_parent> ds(&rank[0], &parent[0]);
boost::initialize_incremental_components(rg, ds);
boost::incremental_components(rg, ds);
map< foreign_key_relationship, relational_edge > table_edges;
for( unsigned i=0; i<foreign_keys.size(); i++ )
connect_relational_vertices( table_edges, foreign_keys, tables_to_connect, table_vertices, rg, ds );
}
return relational_routes;
}
catch( const pqxx_exception &e ){
libpqxx_error( e );
set< foreign_key_relationship > relational_routes;
return relational_routes;
}
}
int main()
{
relational_graph rg;
map<foreign_key_relationship, relational_edge> table_edges;
pqxx::result data;
set<string> tables { "foo", "bar" };
map<string, relational_vertex> table_vertices;
boost::disjoint_sets<relational_rank, relational_parent> ds(relational_rank{}, relational_parent{});
connect_relational_vertices(table_edges, data, tables, table_vertices, rg, ds);
}
I compiled with
gcc 4.8, 4.9, clang 3.5-1
boost 1_56_0
command line:
g++ -std=c++0x -Wall -pedantic -lpthread -g -O0 -isystem ~/custom/boost/ -isystem /usr/include/mpi test.cpp -o test -lmpich -lpqxx
i have to basically edit a quadratic probing file to work as a hash_map library but i'm having trouble overloading the subscript operator so i can modify that specefic index.
the code i have so far is:
template <typename HashedObj, typename storedObj >
class HashTable
{
public:
int& operator [] (const int nIndex)
{
return array[nIndex];//THIS IS WHATS WRONG
}
//create hashtable with siz of 101
explicit HashTable(int size = 101) : array( nextPrime( size ) )
{ makeEmpty( ); }
//return true if current index is active
bool contains( const HashedObj & x ) const
{
return isActive( findPos( x ) );
}
//initiallize index as empty
void makeEmpty( )
{
currentSize = 0;
for( int i = 0; i < array.size( ); i++ )
array[ i ].info = EMPTY;
}
//insert object into hash index and mark index as active
bool insert( const HashedObj & x )
{
// Insert x as active
int currentPos = findPos( x );
if( isActive( currentPos ) )
return false;
array[ currentPos ] = HashEntry( x, ACTIVE );
if( ++currentSize > array.size( ) / 2 )
rehash( );
return true;
}
//search for obj and mark index as deleted
bool remove( const HashedObj & x )
{
int currentPos = findPos( x );
if( !isActive( currentPos ) )
return false;
array[ currentPos ].info = DELETED;
return true;
}
//declare three different entry types
enum EntryType { ACTIVE, EMPTY, DELETED };
private:
//each hash index stores the following
struct HashEntry
{
//THIS WILL BE STRINGS OR INTS
HashedObj element;
//THIS WILL BE VECTOR STRINGS
storedObj ilement;
//index status is stored
EntryType info;
//each entry is made of hashed obj and stored obj and the status is empty
HashEntry( const HashedObj & e = HashedObj( ), const storedObj & f = storedObj( ),EntryType i = EMPTY )
: element( e ), ilement( f ),info( i ) { }
};
//create an array of hashentries
vector<HashEntry> array;
//currentsize of the hash table is stored here
int currentSize;
bool isActive( int currentPos ) const
{ return array[ currentPos ].info == ACTIVE; }
int findPos( const HashedObj & x ) const
{
int offset = 1;
int currentPos = myhash( x );
while( array[ currentPos ].info != EMPTY &&
array[ currentPos ].element != x )
{
currentPos += offset; // Compute ith probe
offset += 2;
if( currentPos >= array.size( ) )
currentPos -= array.size( );
}
return currentPos;
}
void rehash( )
{
vector<HashEntry> oldArray = array;
// Create new double-sized, empty table
array.resize( nextPrime( 2 * oldArray.size( ) ) );
for( int j = 0; j < array.size( ); j++ )
array[ j ].info = EMPTY;
// Copy table over
currentSize = 0;
for( int i = 0; i < oldArray.size( ); i++ )
if( oldArray[ i ].info == ACTIVE )
insert( oldArray[ i ].element );
}
int myhash( const HashedObj & x ) const
{
int hashVal = hashing( x );
hashVal %= array.size( );
if( hashVal < 0 )
hashVal += array.size( );
return hashVal;
}
};
int hashing( const string & key );
int hashing( int key );
the point is for main code to be able to do something like:
wordsByLength[words[i].length()] = words[i];
where words[i] will be a vector. i'm also assuming that i will need to modify the = operator later on but i'm not so sure
Think about what your subscript operator shall return. Is it int&? The simplest choice would be HashEntry:
template <typename HashedObj, typename storedObj >
class HashTable
{
public:
HashEntry& operator [] (int nIndex) // read/write version
{
return array[nIndex];
}
const HashEntry& operator [] (int nIndex) const // read only version
{
return array[nIndex];//THIS IS WHATS WRONG
}
...
};
But it is private. So either make it public - but this breaks somehow your encapsulation.
Because your are inserting HashedObj - then probably this is your desired return type:
template <typename HashedObj, typename storedObj >
class HashTable
{
public:
HashedObj& operator [] (int nIndex) // read/write version
{
return array[nIndex].element;
}
const HashedObj& operator [] (int nIndex) const // read only version
{
return array[nIndex].element;
}
...
};
i am seeing the linker error so need your help.
i have X.dll in which i have a class called DBFieldBase. in my workspace X i am using vector for some data base related applications. the vector which i am using is from thirdparty ospace.
now i am trying to use vector in one more workspace Y. I added the corresponding include files and .lib files in linker->input option in visual studio 2010.
I did dllexport for workspace X and to use it in Y i am using dllimport.
The error which i am getting is given below
X.lib(X.dll) : error LNK2005: "public: class DBFieldBase * &
__thiscall vector::operator[](unsigned int)" (??A?$vector#PAVDBFieldBase####QAEAAPAVDBFieldBase##I#Z) already
defined in sdb.obj
I dont know exactly what is causing this error. The same code was getting successfully compiled in VS 6.0 now i am trying to build it in VS2010. Please let me know if i am missing anything or so.
Thanks in advance.
P.S. I tried to search the solution on internet for similar problem but unfortunately no success.
the code for vector which is from third party is given below:
class os_vector
{
public:
typedef T value_type;
typedef OS_REFERENCE( T ) reference;
typedef OS_CONST_REFERENCE( T ) const_reference;
typedef OS_SIZE_TYPE( T ) size_type;
typedef OS_DIFF_TYPE( T ) difference_type;
typedef OS_ALLOCATOR( T ) allocator_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T* iterator;
typedef const T* const_iterator;
typedef os_reverse_iterator
<
T*,
T,
OS_REFERENCE( T ),
T*,
OS_DIFF_TYPE( T )
> reverse_iterator;
typedef os_reverse_iterator
<
const T*,
T,
OS_CONST_REFERENCE( T ),
const T*,
OS_DIFF_TYPE( T )
> const_reverse_iterator;
// Construct me to be an empty vector.
os_vector() :
start_( 0 ),
finish_( 0 ),
end_of_storage_( 0 ),
alloc_()
{
}
// Construct me to be an empty vector.
explicit os_vector( const OS_ALLOCATOR( T ) & alloc ) :
start_( 0 ),
finish_( 0 ),
end_of_storage_( 0 ),
alloc_( alloc )
{
}
// Construct me to contain `n` ( >0 ) elements. Each element will be
// a copy of `value`.
os_vector
(
size_type n,
const T& value, // = T()
const OS_ALLOCATOR( T ) & alloc // = OS_ALLOCATOR( T )()
) :
start_( 0 ),
finish_( 0 ),
end_of_storage_( 0 ),
alloc_( alloc )
{
assign( n, value );
}
os_vector ( size_type n, const T& value ) :
start_( 0 ),
finish_( 0 ),
end_of_storage_( 0 ),
alloc_()
{
assign( n, value );
}
os_vector ( size_type n ) :
start_( 0 ),
finish_( 0 ),
end_of_storage_( 0 ),
alloc_()
{
assign( n, T() );
}
// Construct me to contain copies of all the elements in `original`.
os_vector( const os_vector OS_ALLOCATE_ARG_2( T, Allocator ) & original ) :
start_( 0 ),
finish_( 0 ),
end_of_storage_( 0 ),
alloc_( original.get_allocator() )
{
assign( original.begin(), original.end() );
}
// Construct me to contain all of the elements in the
// range [`first`, `last`).
template< class InIt >
os_vector
(
InIt first,
InIt last,
const OS_ALLOCATOR( T ) & alloc = OS_ALLOCATOR( T )()
) :
start_( 0 ),
finish_( 0 ),
end_of_storage_( 0 ),
alloc_( alloc )
{
assign( first, last );
}
// Destroy me.
~os_vector()
{
clear();
}
// Replace my contents with a copy of the elements in `original`,
// resizing if necessary.
os_vector OS_ALLOCATE_ARG_2( T, Allocator ) & operator=
(
const os_vector OS_ALLOCATE_ARG_2( T, Allocator ) & original
);
// Remove all my current elements, and then insert the elements
// in range [`first`, `last`).
void assign( const_iterator first, const_iterator last )
{
if ( first == begin() )
erase( begin() + ( last - first ), end() );
else
assign_aux( first, last );
}
// Remove all my current elements, and then insert the elements
// in range [`first`, `last`).
template< class InIt >
void assign( InIt first, InIt last )
{
assign_aux( first, last );
}
// Remove all my current elements, and then insert `n` copies of
// `value`.
void assign( size_type n, const T& value );
void assign( size_type n )
{
assign( n, T() );
}
// Return a copy of the allocator I am using.
allocator_type get_allocator() const
{
return alloc_;
}
// Return a random access iterator positioned at my first element.
iterator begin()
{
return start_;
}
// Return a constant random access iterator positioned at my first
// element.
const_iterator begin() const
{
return start_;
}
// Return a random access iterator positioned immediately after my
// last element.
iterator end()
{
return finish_;
}
// Return a constant random access iterator positioned immediately after
// my last element.
const_iterator end() const
{
return finish_;
}
// Return a random access reverse iterator positioned immediately after
// my last element.
reverse_iterator rbegin()
{
return reverse_iterator( end() );
}
// Return a constant random access reverse iterator positioned
// immediately after my last element.
const_reverse_iterator rbegin() const
{
return const_reverse_iterator( end() );
}
// Return a random access reverse iterator positioned at my first
// element.
reverse_iterator rend()
{
return reverse_iterator( begin() );
}
// Return a constant random access reverse iterator positioned at my
// first element.
const_reverse_iterator rend() const
{
return const_reverse_iterator( begin() );
}
// Return the number of elements that I contain.
size_type size() const
{
return end() - begin();
}
// Return the maximum number of elements that I can contain.
size_type max_size() const
{
return alloc_.max_size();
}
// Cause myself to hold `n` elements, using `value` to expand
// myself if necessary.
void resize( size_type n, T value )
{
if ( n > size() )
insert( end(), n - size(), value );
else
erase( begin() + n, end() );
}
// Cause myself to hold `n` elements using the default constructor
// to expand myself if necessary.
void resize( size_type n )
{
resize( n, T() );
}
// Return the number of elements that I can contain without allocating
// more memory.
size_type capacity() const
{
return end_of_storage_ - start_;
}
// Return true if I contain no elements.
bool empty() const
{
return begin() == end();
}
// Change my capacity to be at least `n`. Does not affect my
// current size.
void reserve( size_type n );
// Return a reference to my `n`th element.
reference operator[]( size_type n )
{
OS_ASSERT_NOT_EMPTY( empty() )
OS_ASSERT_INDEX_OK( n, 0, size() - 1 )
return *( begin() + n );
}
// Return a constant reference to my `n`th element.
const_reference operator[]( size_type n ) const
{
OS_ASSERT_NOT_EMPTY( empty() )
OS_ASSERT_INDEX_OK( n, 0, size() - 1 )
return *( begin() + n );
}
// Return a reference to my `n`th element.
reference at( size_type n )
{
if ( n >= size() )
os_throw_out_of_range();
return *( begin() + n );
}
// Return a constant reference to my `n`th element.
const_reference at( size_type n ) const
{
if ( n >= size() )
os_throw_out_of_range();
return *( begin() + n );
}
// Return a reference to my first element.
reference front()
{
OS_ASSERT_NOT_EMPTY( empty() )
return *begin();
}
// Return a constant reference to my first element.
const_reference front() const
{
OS_ASSERT_NOT_EMPTY( empty() )
return *begin();
}
// Return a reference to my last element.
reference back()
{
OS_ASSERT_NOT_EMPTY( empty() )
return *( end() - 1 );
}
// Return a constant reference to my last element.
const_reference back() const
{
OS_ASSERT_NOT_EMPTY( empty() )
return *( end() - 1 );
}
// Add `value` at my end.
void push_back( const_reference value )
{
if ( finish_ != end_of_storage_ )
{
alloc_.construct( finish_, value );
++finish_;
}
else
insert_aux( end(), value );
}
// Erase my last element.
void pop_back()
{
OS_ASSERT_NOT_EMPTY_ELSE( empty() )
{
--finish_; // not on a single line due to Borland problem
alloc_.destroy( finish_ );
}
}
// Insert `value` at `pos` and return an iterator pointing to the new
// element's position.
iterator insert( iterator pos, const T& value )
{
size_type n = pos - begin();
if ( finish_ != end_of_storage_ && pos == finish_ )
{
alloc_.construct( finish_, value );
++finish_;
}
else
insert_aux( pos, value );
return begin() + n;
}
// Insert an element constructed with the default constructor at `pos` and
// return an iterator pointing to the new element's position.
// not standard, left for backward compatibility
iterator insert( iterator pos )
{
return insert( pos, T() );
}
// Insert `n` copies of `value` at `pos`.
void insert( iterator pos, size_type n, const T& value );
// Insert copies of the elements in range [`first`, `last`) at `pos`.
template< class InIt >
void insert( iterator pos, InIt first, InIt last );
// Erase the element at `pos`.
iterator erase( iterator pos )
{
if ( !( pos + 1 == end() ) )
copy( pos + 1, end(), pos );
pop_back();
return pos;
}
// Erase the elements in range [`first`, `last`).
iterator erase( iterator first, iterator last )
{
iterator i = copy( last, end(), first );
destroy( i, finish_, alloc_ );
finish_ = finish_ - ( last - first );
return first;
}
// Swap my contents with those of `original`.
void swap( os_vector OS_ALLOCATE_ARG_2( T, Allocator ) & original )
{
if ( !(alloc_ == original.alloc_ ) )
{
os_vector OS_ALLOCATE_ARG_2( T, Allocator ) tmp( *this );
assign( original.begin(), original.end() );
original.assign( tmp.begin(), tmp.end() );
}
else
{
::swap( start_, original.start_ );
::swap( finish_, original.finish_ );
::swap( end_of_storage_, original.end_of_storage_ );
::swap( alloc_, original.alloc_ );
}
}
// Erase all of my elements.
void clear()
{
if ( start_ )
{
destroy( start_, finish_, alloc_ );
alloc_.deallocate( start_ );
}
start_ = finish_ = end_of_storage_ = 0;
}
protected:
void insert_aux( T* pos, const T& value );
template< class InIt >
void assign_aux( InIt first, InIt last );
private:
// Data members.
iterator start_;
iterator finish_;
iterator end_of_storage_;
allocator_type alloc_;
public:
// Construct me to contain n ( >0 ) elements. Each element will be
// default constructed.
// This remains for compatibility. It will be removed in a future release.
os_vector
(
const OS_ALLOCATOR( T ) & alloc,
size_type n
) :
start_( 0 ),
finish_( 0 ),
end_of_storage_( 0 ),
alloc_( alloc )
{
assign( n, T() );
}
// Construct me to contain n ( >0 ) elements. Each element will be
// a copy of `value`.
// This remains for compatibility. It will be removed in a future release.
os_vector
(
const OS_ALLOCATOR( T ) & alloc,
size_type n,
const T& value
) :
start_( 0 ),
finish_( 0 ),
end_of_storage_( 0 ),
alloc_( alloc )
{
assign( n, value );
}
// Construct me to contain copies of all the elements in `original`.
// This remains for compatibility. It will be removed in a future release.
os_vector
(
const OS_ALLOCATOR( T ) & alloc,
const os_vector OS_ALLOCATE_ARG_2( T, Allocator ) & original
) :
start_( 0 ),
finish_( 0 ),
end_of_storage_( 0 ),
alloc_( alloc )
{
assign( original.begin(), original.end() );
}
// Construct me to contain all of the elements in the
// range [`first`, `last`).
// This remains for compatibility. It will be removed in a future release.
os_vector
(
const OS_ALLOCATOR( T ) & alloc,
const_iterator first,
const_iterator last
) :
start_( 0 ),
finish_( 0 ),
end_of_storage_( 0 ),
alloc_( alloc )
{
assign( first, last );
}
// Erase all of my elements.
// This remains for compatibility. It will be removed in a future release.
void erase()
{
clear();
}
};
in X.DLL i have a class DBFieldBase its like our our normal class with member variables and functions.
in Y workspace in one of the class i am using vector that usage is given below:
private:
vector < DBFieldBase *> & GetASDVect (void);
vector <DBFieldBase *> m_ASDVect;
Then outside class in same header file there is definition for GetASDVect. its inline
inline vector <DBFieldBase *> & ASD_sdb::GetASDVect (void)
{
return this->m_ASDVect;
}
Let me know if you need anything else from my side.
You've defined a symbol multiple times. I guess a symbol is defined in both X.dll and Y.dll ?