By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,389 Members | 1,878 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,389 IT Pros & Developers. It's quick & easy.

underfined inline function.

P: n/a
sam
Hi,

I can't figure out what is the problem of the following coding.
#ifndef __PARSER__
#define __PARSER__

#include <iostream>
#include <string>
#include <fstream>
//#include <exception>
#include <iomanip> // Header for I/O stream manipulators
#include <ext/hash_map>
#include <vector>
#include <list>

#define LLEN 256

// Namespace alias to reach hash_map classes
namespace stdext = ::__gnu_cxx;
using namespace std;
using namespace stdext;

/* struct or */
class HashString
{
public:
/*long*/ int operator()(std::string const &str) const
{
return stdext::hash<char const *>()(str.c_str());
}
};

// This class' function operator() tests if any two keys are equal.

/* struct or */
class HashStringCompare
{
public:
bool operator()(std::string s1, std::string s2) const
{
return s1 == s2;
}
};

class HashMap: public hash_map<string, string, HashString,
HashStringCompare>
{
public:
HashMap(): hash_map<string, string, HashString, HashStringCompare>() {}
};

#define SPACES " \t\n\r" // default "spaces" for trimming strings

class Parser
{
public:
Parser(string &cmd);
Parser(ifstream &f);
virtual int parse() {return 1;};
void _debug(list<HashMap> &l);

// trim spaces from right (you can define what spaces are)
string trim_right (const string & s, const string & t = SPACES);
// trim spaces from left
string trim_left (const string & s, const string & t = SPACES);
// trim spaces from both sides
string trim (const string & s, const string & t = SPACES);

virtual ~Parser() {};

protected:
vector<string> v_data;
};

inline string trim_right (const string & s, const string & t)
{
string d (s);
string::size_type i (d.find_last_not_of (t));
if (i == string::npos)
return "";
else
return d.erase (d.find_last_not_of (t) + 1) ;
} // end of trim_right

inline string trim_left (const string & s, const string & t)
{
string d (s);
return d.erase (0, s.find_first_not_of (t)) ;
} // end of trim_left

inline string trim (const string & s, const string & t)
{
string d (s);
return trim_left (trim_right (d, t), t) ;
} // end of trim

inline Parser::Parser(string &cmd)
{
const char *s = cmd.c_str();
string str = trim(s);
if (str.c_str()[0] == '#' || str.length() == 0)
cout << "this is comment: " << str << endl;
else
v_data.push_back(str);
}

int main()
{
string s = " test string ";
Parser p(s);
}

#endif
When compiled with g++ in FreeBSD 5.4, it generated error shown as follow:
# g++ p_test.cpp
/var/tmp//ccJnnMuA.o(.gnu.linkonce.t._ZN6ParserC1ERSs+0xd8): In function
`Parser::Parser(std::string&)':
: undefined reference to `Parser::trim(std::string const&, std::string
const&)'
Jul 23 '05 #1
Share this Question
Share on Google+
4 Replies


P: n/a
sam wrote:
....

class Parser
{
public:
Parser(string &cmd);
Parser(ifstream &f);
virtual int parse() {return 1;};
void _debug(list<HashMap> &l);

// trim spaces from right (you can define what spaces are)
string trim_right (const string & s, const string & t = SPACES);
// trim spaces from left
string trim_left (const string & s, const string & t = SPACES);
// trim spaces from both sides
string trim (const string & s, const string & t = SPACES); This is defined as a regular member function.
virtual ~Parser() {};

protected:
vector<string> v_data;
}; ....
inline string trim (const string & s, const string & t) This is defined as a global function. {
string d (s);
return trim_left (trim_right (d, t), t) ;
} // end of trim

Did you mean:

inline string Parser::trim (const string & s, const string & t)

?

Since these functions do not access the object in any way, you can
declare them static member functions. (and probably should).
inline Parser::Parser(string &cmd)
{
const char *s = cmd.c_str();
string str = trim(s); This accesses the member function. if (str.c_str()[0] == '#' || str.length() == 0)
cout << "this is comment: " << str << endl;
else
v_data.push_back(str);
}

int main()
{
string s = " test string ";
Parser p(s);
}

#endif
When compiled with g++ in FreeBSD 5.4, it generated error shown as follow:
# g++ p_test.cpp
/var/tmp//ccJnnMuA.o(.gnu.linkonce.t._ZN6ParserC1ERSs+0xd8): In function
`Parser::Parser(std::string&)':
: undefined reference to `Parser::trim(std::string const&, std::string
const&)'


Not the linker is looking for Parser::trim. You have defined ::trim.
Jul 23 '05 #2

P: n/a
class Parser
{ ..... // trim spaces from both sides
string trim (const string & s, const string & t = SPACES); ..... }; trim is declarated as a member function of Parser
inline string trim (const string & s, const string & t)
{
string d (s);
return trim_left (trim_right (d, t), t) ;
} // end of trim Here it is defined as a global function
inline Parser::Parser(string &cmd)
{ ..... string str = trim(s); ...... } Here the member function trim is called, not the global function.
`Parser::Parser(std::string&)':
: undefined reference to `Parser::trim(std::string const&, std::string
const&)' This is because Parser::trim is declared but not defined.

My guess is that you forgot to qualify the member function name in the definition
as below: inline string Parser::trim (const string & s, const string & t)
{
string d (s);
return trim_left (trim_right (d, t), t) ;
} // end of trim


Alternatively you may remove the declaration in Parser since trim does not
need to be a Parser member.

---
Thierry Miceli
www.ideat-solutions.com

Jul 23 '05 #3

P: n/a
sam
Thierry Miceli wrote:
class Parser
{
....
// trim spaces from both sides
string trim (const string & s, const string & t = SPACES);


....
};


trim is declarated as a member function of Parser
inline string trim (const string & s, const string & t)
{
string d (s);
return trim_left (trim_right (d, t), t) ;
} // end of trim


Here it is defined as a global function
inline Parser::Parser(string &cmd)
{


....
string str = trim(s);


.....
}


Here the member function trim is called, not the global function.
`Parser::Parser(std::string&)':
: undefined reference to `Parser::trim(std::string const&, std::string
const&)'


This is because Parser::trim is declared but not defined.

My guess is that you forgot to qualify the member function name in the
definition as below:
inline string Parser::trim (const string & s, const string & t)
{
string d (s);
return trim_left (trim_right (d, t), t) ;
} // end of trim

Alternatively you may remove the declaration in Parser since trim does
not need to be a Parser member.

Thanks for the help.
In regarding to moving the trim() stuff to another class, I decided to
create a seperate static class to hold this sort of functions.
Do you think the following static class declaration is fine?
But I m not sure whether a static constructor/destructor is neccessary.

class TextUtil
{
public:
// trim spaces from right (you can define what spaces are)
static string trim_right (const string & s, const string & t =
SPACES);
// trim spaces from left
static string trim_left (const string & s, const string & t =
SPACES);
// trim spaces from both sides
static string trim (const string & s, const string & t = SPACES);

private:
//TextUtil() {};
};

Thanks
Sam
---
Thierry Miceli
www.ideat-solutions.com

Jul 23 '05 #4

P: n/a
sam wrote:

class TextUtil
{
public:
static string trim_right (const string & s,
const string & t = SPACES);
static string trim_left (const string & s,
const string & t = SPACES);
static string trim (const string & s,
const string & t = SPACES);

private:
//TextUtil() {};
};


It looks like you would be better off with a namespace:

namespace TextUtil
{
string trim_right(const string &s,
const string &t = SPACES);
};

I don't see anything gained by the class-with-static-members
approach over the namespaces approach. But the namespaces
approach gives you the ability to import symbols with 'using'.

Jul 23 '05 #5

This discussion thread is closed

Replies have been disabled for this discussion.