with the given code, How do i call insert from main?
I tried, but I always got error :expected primary-expression before.
what is the primary-expression exactly?
Object & front( )
{ return *begin( ); }
const Object & front( ) const
{ return *begin( ); }
Object & back( )
{ return *--end( ); }
const Object & back( ) const
{ return *--end( ); }
void push_front( const Object & x )
{ insert( begin( ), x ); }
void push_back( const Object & x )
{ insert( end( ), x ); }
void pop_front( )
{ erase( begin( ) ); }
void pop_back( )
{ erase( --end( ) ); }
// Insert x before itr.
iterator insert( iterator itr, const Object & x )
{
Node *p = itr.current;
theSize++;
return iterator( p->prev = p->prev->next = new Node( x, p->prev, p ) );
}
To call a function from main:
void My_Function()
{
std::cout << "My_Function\n"
}
int main()
{
My_Function();
return 0;
}
To call an object's method from main:
class Object
{
public:
void print() { std::cout << "Object\n";}
};
int main()
{
Object o;
o.print();
return 0;
}
You should be able to find these examples in some good C++ textbooks.
Edit 1: Static Object functions
You could also declare a method as static inside an object:
class Object_With_Static
{
public:
static void Print_Name()
{
std::cout << "Object_With_Static\n";
};
};
int main()
{
Object_With_Static::Print_Name();
return 0;
}
Related
I have a problem with the following class. I get error "Tree.cpp:12:56: error: type/value mismatch at argument 2 in template parameter list for ‘template class std::multiset’ // Tree.cpp:12:56: note: expected a type, got ‘(Tree::compare < )’". I don't understand how I should pass the comparator type in the multiset declaration. Could you help me?
#include <set>
#include <deque>
#include <iostream>
using namespace std;
template <typename T>
class Tree
{
typedef typename std::multiset<Tree<T>*, typename Tree<T>::compare > NodeSet;
private:
NodeSet children;
T content;
public:
struct compare
{
bool operator()( const Tree*& t1, const Tree*& t2 ) const
{
cout << "Comparing " << t1->GetContent() << " vs " << t2->GetContent() << endl;
return t1->GetContent() < t2->GetContent();
}
};
Tree& AppendNode( const T& node )
{
Tree* t = new Tree( node );
AttachTree( t );
return *t;
}
void Clear()
{
typename NodeSet::iterator it = children.begin();
while( children.size() != 0 && children.end() != it )
{
children.erase( *it );
delete *it;
it++;
}
}
Tree( const T& root )
{
content = root;
}
void AttachTree( Tree* t )
{
children.insert( t );
}
void Visit( std::deque<T>& exp ) const
{
exp.push_back( content );
typename NodeSet::iterator it = children.begin();
while( it != children.end() )
{
( *it )->Visit( exp ); it++;
}
}
Tree()
{}
Tree( Tree& c )
{
c.DeepCopyTo( this );
}
T& operator =( const Tree& b )
{
b.DeepCopyTo( this );
}
~Tree()
{
cout << "in destructor for" << this << endl;
Clear();
}
void DeepCopyTo( Tree* dest ) const
{
dest->content = content;
typename NodeSet::iterator it = children.begin();
while( it != children.end() )
{
Tree* t = new Tree();
( *it )->DeepCopyTo( t );
dest->AttachTree( t );
it++;
}
}
void Print()
{
typename NodeSet::iterator it = children.begin();
while( it != children.end() )
{
cout << *it << ",";
it++;
}
}
};
int main()
{
Tree<int> tree( 8 );
tree.AppendNode( 5 );
}
You might want to change this line to
typedef
typename std::multiset<Tree*, typename Tree::compare >
NodeSet;
Note that compare is a dependent name, so you need to use typename.
Also, you should consider moving the struct compare above this line, as this line references it.
Two more things to notice.
You might want to change compare to
struct compare {
bool operator()(const Tree* t1, const Tree* t2) const {
cout << "Comparing " <<t1->GetContent() <<" vs "<<t2->GetContent()<<endl;
return t1->GetContent() < t2->GetContent();
}
};
unfortunately, GetContent doesn't seem defined anywhere in your code.
I thought this is already very simple and not doing much (Took it from one of the stack overflow question answer code), but running a loop of 100K times shows it's slower than boost::shared_ptr. Baffled, where is the slowness come from?
template <class T>
class sp_shared_ptr
{
public:
inline sp_shared_ptr() noexcept: p_(), count_() {}
inline explicit sp_shared_ptr( T* p ) noexcept: p_( p ), count_( new int(1) ) {}
inline sp_shared_ptr( const sp_shared_ptr& sp ) noexcept: p_( sp.p_ ), count_( sp.count_ )
{
if( count_ ) ++(*count_);
}
// EDIT: add in later based on comments
sp_shared_ptr( sp_shared_ptr && r ) noexcept : p_( r.p_ ), count_()
{
int *tmp = r.count_;
r.count_ = count_;
count_ = tmp;
r.p_ = 0;
}
sp_shared_ptr& operator=( const sp_shared_ptr& sp ) noexcept
{
if( this != &sp )
{
clear();
p_ = sp.p_;
count_ = sp.count_;
if( count_ ) ++*count_;
}
return *this;
}
~sp_shared_ptr() noexcept
{
clear();
}
private:
inline void clear() noexcept
{
if( count_ )
{
--*count_;
if( *count_ == 0 ) {
delete p_; p_=0;
delete count_; count_=0;
}
}
}
T* get() const { return count_ ? p_ : 0; }
T* operator->() const { return get(); }
T& operator*() const { return *get(); }
T* p_;
int* count_;
};
The output of the following program is:
10229594
14577150
14030158
EDIT: Based on #BoPersson's comment, edit in the move constructor. Now, result is getting closer:
10201099
14121221
14040181
I wonder why it is faster, or quite a bit faster (No atomic counter didn't do any good in my test?)
Calling program:
#include <iostream>
#include <map>
#include <string>
#include <boost/shared_ptr.hpp>
#include <boost/smart_ptr.hpp>
#include <time.h>
#include "sp_shared_ptr.h"
struct A
{
int a1;
double a2;
std::string a3;
};
long long duration( const timespec& t0, const timespec& t1 )
{
return (t1.tv_sec*1000000000L + t1.tv_nsec) - (t0.tv_sec*1000000000L + t0.tv_nsec);
}
int main()
{
typedef std::vector<std::unique_ptr<A>> UPVector;
typedef std::vector<boost::shared_ptr<A>> SPVector;
typedef std::vector<sp_shared_ptr<A>> MySPVector;
UPVector v1;
SPVector v2;
MySPVector v3;
const int n=100000;
timespec t0, t1;
clock_gettime( CLOCK_REALTIME, &t0 );
clock_gettime( CLOCK_REALTIME, &t0 );
{
for( auto i=0; i < n; ++i )
v1.push_back( std::unique_ptr<A>( new A { i, i/100.0, "aaaaaaaaaa" } ) );
}
clock_gettime( CLOCK_REALTIME, &t1 );
std::cout << duration( t0, t1 ) << std::endl;
clock_gettime( CLOCK_REALTIME, &t0 );
{
for( auto i=0; i < n; ++i )
v3.push_back( sp_shared_ptr<A>( new A{ i, i/100.0, "aaaaaaaaaa" } ) );
}
clock_gettime( CLOCK_REALTIME, &t1 );
std::cout << duration( t0, t1 ) << std::endl;
clock_gettime( CLOCK_REALTIME, &t0 );
{
for( auto i=0; i < n; ++i )
v2.push_back( boost::shared_ptr<A>( new A{ i, i/100.0, "aaaaaaaaaa" } ) );
}
clock_gettime( CLOCK_REALTIME, &t1 );
std::cout << duration( t0, t1 ) << std::endl;
return 0;
}
My team designed a library meant to store data from different "signals". A signal is a list of timestamped float values. We have three way to store a signal (depending of the way it was recorded from the hardware in the first place):
MarkerSignal: We store a sorted std::vector of std::pair of (boost::posix_time::ptime,float)
RawSignal: We store a start time (boost::posix_time::ptime), a sampling period (boost::posix_time::time_duration) and finally a std::vector of float (each value's timestamp is start time + period * value's index in the vector)
NumericalSignal: We store a start time (boost::posix_time::ptime), a sampling period (boost::posix_time::time_duration), a scale (float), an offset (float) and finally a std::vector of short (timestamp is computed as for RawSignal and float value is short*scale+offset)
Those three signals have a common parent class (SignalBase) storing the signal's name, description, unit and stuff like that. We use the visitor pattern to let people nicely "cast" the SignalBase to a MarkerSignal/RawSignal/NumericalSignal and then access the data it contains.
In the end, what we need for each class is to iterate through all elements, one element being actually a pair of (boost::posix_time::ptime,float) (like MarkerSignal). And it's a pain having to create a visitor every time we want to do that.
Storing all signals as a std::vector<std::pair<boost::posix_time::ptime,float>> (or returning an object of this kind on demand) uses too much memory.
We thought the best was probably to define our own iterator object. The iterator would give access to the timestamp and value, like that:
SignalBase* signal = <any signal>;
for ( SignalBase::iterator iter = signal->begin();
iter != signal->end();
++iter )
{
boost::posix_time::ptime timestamp = iter.time();
float value = iter.value();
}
What's the best approach/strategy to create such an iterator class? (simple class with a size_t index attribute, or a MarkerSignal/RawSignal/NumericalSignal container's specific iterator as attribute, store a std::pair<boost::posix_time::ptime,float> and update it from a ++ operator...).
Also, I would much prefer if the solution rpoposed avoids using a virtual table (to have ++, time(), and value() be faster when iterating on huge signals).
To sum up I think the best you can achieve if you value for efficiency could be something like this:
template <typename SignalType, typename Functor = function<void(typename SignalType::value_type&&) > >
void iterateThroughSignal(SignalBase *signal, Functor foo) {
SignalType *specificSignal = dynamic_cast<SignalType *>(signal);
if (!specificSignal)
return;
for (typename SignalType::iterator it = specificSignal->begin();
it != specificSignal->end();
it++) {
foo(*it); // retrieving value from iterator...
}
}
Then for call:
iterateThroughSignal<MarkerSignal>(signal, [](MarkerSignal::value_type&& msv){
/*doing something with value...*/
});
I'm not sure if you are using C++11 so the lambda can be replace by function pointer, rvalue reference using lvalue reference and the std::function with a function signature...
Edit:
To make it compile when the type of the foo signature won't match the SignalType::value_type there will be a need of playing a little bit with sfinae:
template <typename SignalType>
class IterateHelper {
template <typename Functor>
static typename enable_if<first_param_is<Functor, typename SignalType::value_type>::value >::type iterateThroughSignal(SignalBase *signal, Functor foo) {
SignalType *specificSignal = dynamic_cast<SignalType *>(signal);
if (!specificSignal)
return;
for (typename SignalType::iterator it = specificSignal->begin();
it != specificSignal->end();
it++) {
foo(*it); // retrieving value from iterator...
}
}
template <typename Functor>
static typename enable_if<!first_param_is<Functor, typename SignalType::value_type>::value >::type iterateThroughSignal(SignalBase *signal, Functor foo) {
}
};
I leave the implementation of first_param_is helper struct to you... Call would change to:
IteratorHelper<MarkerSignal>::iterateThroughSignal(signal, [](MarkerSignal::value_type&& msv){
/*doing something with value...*/
});
As I wanted something easy to use for people using my library (be able to esily do a for loop) I finally implemented my own iterator like that:
Added two virtual functions in SignalBase (found no alternative to that, runtime will use the virtual table):
virtual size_t floatDataCount() const = 0;
virtual bool loadFloatInfoAt( size_t pos, SignalFloatIter::ValueInfo& info ) const = 0;
Added functions in SignalBase to get begin/end iterators:
inline BDL::SignalFloatIter beginFloatIter() const { return BDL::SignalFloatIter::beginIter( *this ); }
inline BDL::SignalFloatIter endFloatIter() const { return BDL::SignalFloatIter::endIter( *this ); }
Declared iterator class like that:
class SignalFloatIter
{
public:
SignalFloatIter( const SignalBase* signal = NULL, size_t pos = 0 );
SignalFloatIter( const SignalFloatIter& iter );
static SignalFloatIter beginIter( const SignalBase& signal );
static SignalFloatIter endIter( const SignalBase& signal );
SignalFloatIter& operator=( const SignalFloatIter& iter );
bool operator==( const SignalFloatIter& iter ) const;
bool operator!=( const SignalFloatIter& iter ) const;
/** Pre-increment operator */
SignalFloatIter& operator++();
/** Post-increment operator */
SignalFloatIter operator++(int unused);
inline const BDL::time& when() const { assert( m_valid ); return m_info.first.first; }
inline const BDL::duration& duration() const { assert( m_valid ); return m_info.first.second; }
inline const float& value() const { assert( m_valid ); return m_info.second; }
inline size_t index() const { assert( m_valid ); return m_pos; }
inline BDL::MarkerKey markerKey() const { assert( m_valid ); return std::make_pair( when(), duration() ); }
inline bool valid() const { return m_valid; }
typedef std::pair<BDL::time,BDL::duration> TimeInfo;
typedef std::pair<TimeInfo,float> ValueInfo;
private:
const SignalBase* m_signal;
size_t m_pos;
bool m_valid;
ValueInfo m_info;
void loadCurInfo();
};
Implemented:
SignalFloatIter::SignalFloatIter( const SignalBase* signal, size_t pos ) :
m_signal( signal ),
m_pos( pos )
{
loadCurInfo();
}
SignalFloatIter::SignalFloatIter( const SignalFloatIter& iter )
{
operator=( iter );
}
SignalFloatIter SignalFloatIter::beginIter( const SignalBase& signal )
{
return SignalFloatIter( &signal, 0 );
}
SignalFloatIter SignalFloatIter::endIter( const SignalBase& signal )
{
return SignalFloatIter( &signal, signal.floatDataCount() );
}
SignalFloatIter& SignalFloatIter::operator=( const SignalFloatIter& iter )
{
if ( this != &iter )
{
m_signal = iter.m_signal;
m_pos = iter.m_pos;
m_info = iter.m_info;
m_valid = iter.m_valid;
}
return *this;
}
bool SignalFloatIter::operator==( const SignalFloatIter& iter ) const
{
if ( m_signal == iter.m_signal )
{
if ( m_pos == iter.m_pos )
{
assert( m_valid == iter.m_valid );
if ( m_valid )
assert( m_info == iter.m_info );
return true;
}
else
{
return false;
}
}
else
{
assert( false );
return false;
}
}
bool SignalFloatIter::operator!=( const SignalFloatIter& iter ) const
{
return !( *this == iter );
}
SignalFloatIter& SignalFloatIter::operator++()
{
++m_pos;
loadCurInfo();
return *this;
}
SignalFloatIter SignalFloatIter::operator++( int unused )
{
SignalFloatIter old = *this;
assert( unused == 0 ); // see http://en.cppreference.com/w/cpp/language/operator_incdec
++m_pos;
loadCurInfo();
return old;
}
void SignalFloatIter::loadCurInfo()
{
if ( m_signal )
{
m_valid = m_signal->loadFloatInfoAt( m_pos, m_info );
}
else
{
assert( false );
m_valid = false;
}
}
It's pretty straightforward and easy to use for any signal:
std::cout << "Signal timestamped data are: ";
for ( BDL::SignalFloatIter iter = signal.beginFloatIter();
iter != signal.endFloatIter();
++iter )
{
std::cout << iter.when() << " : " << iter.value() << std::endl;
}
Background
Large application with a bundle of code, I can't change the storage mechanism.
I would like to create an iterator over a set of multi-dimensional data stored in parallel arrays so we can start using std algorithms & containers.
Any ideas on how to make this work correctly?
#include <boost/iterator/iterator_facade.hpp>
#include <iostream>
#include <algorithm>
class curve_point_iterator;
const int curve_size = 10;
class curve
{
public:
curve()
{
std::fill( x, &x[curve_size], 0.0 );
std::fill( y, &y[curve_size], 0.0 );
}
double x[curve_size];
double y[curve_size];
curve_point_iterator begin();
curve_point_iterator end();
};
class point_reference
{
public:
point_reference( double& x_, double& y_ )
: x( x_ )
, y( y_ )
{
}
point_reference& operator = ( point_reference& other )
{
x = other.x;
y = other.y;
return *this;
}
double & x;
double & y;
};
class curve_point_iterator
: public boost::iterator_facade<
curve_point_iterator
, point_reference
, boost::random_access_traversal_tag >
{
public:
curve_point_iterator()
: index(0)
, curve_(nullptr)
{}
explicit curve_point_iterator( curve* curve_in, size_t index_ = 0 )
: index( index_ )
, curve_( curve_in )
{}
private:
friend class boost::iterator_core_access;
void increment()
{
++index;
}
void decrement()
{
--index;
}
void advance( size_t n )
{
index += n;
}
difference_type distance_to( curve_point_iterator const& other ) const
{
return other.index - this->index;
}
bool equal(curve_point_iterator const& other) const
{
return this->index == other.index && this->curve_ == other.curve_;
}
point_reference& dereference() const
{
auto pt_ref = new( point_reference_buffer ) point_reference( curve_->x[index]
, curve_->y[index] );
return *pt_ref;
}
size_t index;
mutable char point_reference_buffer[sizeof(point_reference)];
curve* curve_;
};
curve_point_iterator curve::begin()
{
return curve_point_iterator( this );
}
curve_point_iterator curve::end()
{
return curve_point_iterator( this, curve_size+1 );
}
int main(int argc, char* argv[])
{
curve crv;
crv.x[1] = 20;
crv.x[2] = 10;
std::sort( crv.begin(), crv.end(), []( point_reference const& a, point_reference const& b )
{
return a.x < b.x;
});
for( auto i = 0; i < curve_size; ++i )
{
std::cout << crv.x[i] << std::endl;
}
return 0;
}
Output
0
20
20
20
20
20
20
20
20
20
After changing to
class point_reference
{
... ( all the other stuff )
double x; // no longer reference
double y; // no longer reference
};
Output
0
20
10
0
0
0
0
0
0
Okay, what you need to do is to introduce a point type (which has value semantics) in addition to point_reference, which has the reference semantics you're looking for. You need the value semantics so that operations such as swap act as the standard expects. You can use the fourth argument of iterator_facade to allow this. Also, this way there is no need to use that mutable buffer, since the point_reference itself is returned by value.
Also, your curve::end() used the wrong index, and should use curve_size as its index.
#include <boost/iterator/iterator_facade.hpp>
#include <iostream>
#include <algorithm>
class curve_point_iterator;
const int curve_size = 10;
class curve
{
public:
curve()
{
std::fill( x, &x[curve_size], 0.0 );
std::fill( y, &y[curve_size], 0.0 );
}
double x[curve_size];
double y[curve_size];
curve_point_iterator begin();
curve_point_iterator end();
};
class point
{
public:
point( const double& x_, const double& y_ )
: x( x_ )
, y( y_ )
{
}
double x;
double y;
};
class point_reference
{
public:
point_reference( double& x_, double& y_ )
: x( x_ ),
y( y_ )
{
}
point_reference& operator = ( const point& other )
{
x = other.x;
y = other.y;
return *this;
}
operator point() const
{
return point(x, y);
}
double & x;
double & y;
point_reference& operator=(const point_reference& other)
{
x = other.x;
y = other.y;
}
point_reference* operator->()
{
return this;
}
point_reference* operator->() const
{
return this;
}
};
class curve_point_iterator
: public boost::iterator_facade<
curve_point_iterator
, point
, boost::random_access_traversal_tag
, point_reference>
{
public:
curve_point_iterator()
: index(0)
, curve_(nullptr)
{}
explicit curve_point_iterator( curve* curve_in, size_t index_ = 0 )
: index( index_ )
, curve_( curve_in )
{}
point_reference operator->() const
{
return dereference();
}
private:
friend class boost::iterator_core_access;
void increment()
{
++index;
}
void decrement()
{
--index;
}
void advance( size_t n )
{
index += n;
}
difference_type distance_to( curve_point_iterator const& other ) const
{
return other.index - this->index;
}
bool equal(curve_point_iterator const& other) const
{
return this->index == other.index && this->curve_ == other.curve_;
}
point_reference dereference() const
{
// auto pt_ref = new( point_reference_buffer ) point_reference( curve_->x[index]
// , curve_->y[index] );
// return *pt_ref;
return point_reference(curve_->x[index], curve_->y[index]);
}
size_t index;
curve* curve_;
};
curve_point_iterator curve::begin()
{
return curve_point_iterator( this );
}
curve_point_iterator curve::end()
{
return curve_point_iterator( this, curve_size );
}
int main(int argc, char* argv[])
{
curve crv;
crv.x[1] = 20;
crv.x[2] = 10;
std::sort( crv.begin(), crv.end(), []( point const& a, point const& b )
{
return a.x < b.x;
});
for( auto i = 0; i < curve_size; ++i )
{
std::cout << crv.x[i] << std::endl;
}
return 0;
}
Output:
0
0
0
0
0
0
0
0
10
20
for my data structures class, we are making a data structure that we can use to easily store and organize data. I am having an issue with the output function of my tree. The error message that I get is:
AccountDB.cpp: In member function ‘void AccountDB::output(std::ostream&) const’:
AccountDB.cpp:23:21: error: passing ‘const AccountDB’ as ‘this’ argument of ‘void
AccountDB::output(std::ostream&, const AccountDB::Elem*)’ discards qualifiers [-fpermissive]
I've been looking around and my output code looks pretty similar to what other people have done. I have no idea, and I don't really understand what the error is trying to tell.
Thanks for your help.
Header:
#ifndef ACCOUNTDB_H
#define ACCOUNTDB_H
#include <iostream>
using namespace std;
#include "AccountRecord.h"
class AccountDB {
public:
AccountDB();
~AccountDB();
void insert( const AccountRecord &v );
AccountRecord * get( const AccountRecord &v );
void output( ostream &s ) const;
private:
struct Elem {
AccountRecord info;
Elem *left;
Elem *right;
};
Elem *root;
void insert( const AccountRecord &v, Elem *&e );
AccountRecord * get( const AccountRecord &v, Elem *&e );
void output( ostream &s, const Elem *e );
};
ostream &operator << ( ostream &s, const AccountDB &v );
#endif
Source
#include "AccountDB.h"
//default constructor
AccountDB::AccountDB() {
root = 0;
}
//destructor
AccountDB::~AccountDB() {
}
//public
void AccountDB::insert( const AccountRecord &v ) {
return insert( v, root );
}
AccountRecord * AccountDB::get( const AccountRecord &v ) {
return get( v, root );
}
void AccountDB::output( ostream &s ) const {
output( s, root );
}
//private
void AccountDB::insert( const AccountRecord &v, Elem *&e ) {
if( e == NULL ) {
e = new Elem();
e->info = v;
}
else if( v < e->info )
insert( v, e->left );
else if( v > e->info )
insert( v, e->right );
}
AccountRecord * AccountDB::get( const AccountRecord &v, Elem *&e ){
if( e->info == v )
return &(e->info);
else if( v < e->info && e->left != NULL )
get( v, e->left );
else if( v > e->info && e->right != NULL )
get( v, e-> right );
else
return NULL;
}
void AccountDB::output( ostream &s, const Elem *e ) {
if( e != NULL ) {
output( s, e->left );
s << e->info << endl;
output( s, e->right );
}
}
ostream &operator << ( ostream &s, const AccountDB &v ) {
v.output( s );
return s;
}
Your output function is not declared const, so when you call
output( s, root );
the compiler tells you that you are calling a non-const function from inside a const function.
There are several ways to deal with this - one is to make output const; the other is to make output static (if you can).
The error is that
void AccountDB::output( ostream &s, const Elem *e )
is not declared as const, but you call it from a const method.
Change the declaration (and definition) to:
void output( ostream &s, const Elem *e ) const;
You can do this since you're not modifying any members inside the function.