Using Templates Inside a Namespace - c++

I asked this question yesterday and thought I got to the bottom of the problem... But alas it seems to be something else. I haven't the faintest idea what the issue could be, but this error is being thrown using the the following code:
Error:
a2main.cpp:36:21: error: no member named 'readJSON' in namespace 'json'
out = json::readJSON(data_dir + "a2-empty_object.json", e, debug);
~~~~~~^
main.cpp
#include <iostream>
#include <string>
#include "Object.h"
int main(){
std::string out;
out = json::readJSON(data_dir + "a2-empty_object.json", e, debug);
}
Object.h
#ifndef _JSON_READER_H_
#define _JSON_READER_H_
namespace json{
enum JSON_TYPE {
UNKNOWN, EMPTY, ARRAY_OPEN, ARRAY_CLOSE, OBJECT_OPEN, OBJECT_CLOSE, NV_PAIR
};
std::string trim(const std::string& str);
std::string trim(const std::string& str, char c);
std::string getName(const std::string& str);
std::string getValue(const std::string& str);
JSON_TYPE get_json_type(std::string s);
template<typename T>
List <T, OBJECTS_PER_JSON_FILE>* deserializeJSON(std::string filename, T obj, bool debug) {
std::ifstream fin(filename);
if (fin.fail()){
throw std::string("Couldn't open: " + filename);
}
std::string fline, line, n,v;
bool done=false;
auto list = new List <T, OBJECTS_PER_JSON_FILE>();
return list;
}
template<typename T>
std::string readJSON(std::string jsonFile, T& object, bool debug = false, char delimiter = ',') {
std::string string_of_values = "test";
return string_of_values;
}
}
#endif
Why is it throwing an error that the function is not in the namespace? It seems rather odd. Could it be a template issue? Thanks!
EDIT:
In file included from a2main.cpp:13:
./JSONReader.h:60:2: error: unknown type name 'List'
List <T, OBJECTS_PER_JSON_FILE>* deserializeJSON(std::string filename, T obj, bool debug) {
^
./JSONReader.h:60:7: error: expected unqualified-id
List <T, OBJECTS_PER_JSON_FILE>* deserializeJSON(std::string filename, T obj, bool debug) {
^

Related

C++ Multiple Definitions of Blank Header FIle

I've been searching around for the answer to this but so far nothing has worked.
I have two files that were provided to me for a Parser assignment, lex.h and parse.h. The lex.h file was used in a previous assignment and works fine, the parse.h file is giving me issues. The parse.h file looks like this:
#ifndef PARSE_H_
#define PARSE_H_
#include <iostream>
#include <map>
using namespace std;
#include "lex.h"
//using std::map;
map<string, bool> defVar;
namespace Parser {
bool pushed_back = false;
LexItem pushed_token;
static LexItem GetNextToken(istream& in, int& line) {
if( pushed_back ) {
pushed_back = false;
return pushed_token;
}
return getNextToken(in, line);
}
static void PushBackToken(LexItem & t) {
if( pushed_back ) {
abort();
}
pushed_back = true;
pushed_token = t;
}
}
static int error_count = 0;
void ParseError(int line, string msg)
{
++error_count;
cout << line << ": " << msg << endl;
}
extern bool Prog(istream& in, int& line);
extern bool StmtList(istream& in, int& line);
extern bool Stmt(istream& in, int& line);
extern bool PrintStmt(istream& in, int& line);
extern bool IfStmt(istream& in, int& line);
extern bool Var(istream& in, int& line);
extern bool AssignStmt(istream& in, int& line);
extern bool ExprList(istream& in, int& line);
extern bool Expr(istream& in, int& line);
extern bool Term(istream& in, int& line);
extern bool Factor(istream& in, int& line);
#endif /* PARSE_H_ */
Analyzer Class
#include <regex>
#include "lex.h"
/**
* Relates token type to string
*/
static std::map<Token, std::string> tokenPrint {
// Code not provided for readability
};
/**
* Operator overloading << for Token object
*/
ostream& operator<<(ostream& out, const LexItem& tok) {
// Code not provided for readability
}
/**
* Current token is used to set previous token before returned
* Previous token is used to compare to the current token and check
* for invalid arangment such as no begin token.
*/
LexItem currentToken;
LexItem previousToken;
/**
* Return the next token within a file
*/
LexItem getNextToken(istream& in, int& linenum) {
enum TokenState { START, INID, INSTRING, ININT, INREAL, INCOMMENT, SIGN} lexstate = START;
std::string lexeme;
char character;
// Code not provided for readability
}
Parse.cpp
#include "parse.h"
bool Prog(istream& in, int& line) {
return false;
}
bool StmtList(istream& in, int& line) {
return false;
}
// All the rest return false too
Tester.cpp
#include <iostream>
#include <fstream>
#include <vector>
#include <sstream>
#include <map>
#include "parse.h"
int main(int argc, char** argv) {
// Reads file and handles errors
// Code not provided for readability
while (true) {
Parse::getNextToken(file, lineNumber);
}
}
I have an Analyzer.cpp file that uses lex.h as a header for the Analyzer and I have a Parse.cpp that uses parse.h for the Parser. In the main program I use the parse.h header file.
I keep getting a multiple definition error with defVar, Parse::pushed_back, Parser::pushed_token, and ParseError(...). I cannot edit lex.h or parse.h as they are given to me and can only change the contents of Analyzer.cpp, Parser.cpp, and Tester.cpp. I can post all the code if necessary.
I'm fairly new to c++ but all the header files have the header guards and none of the functions are ever defined twice. I have looked at other problems but nothing seems to be working. Any help is greatly appreciated.

Does not match in any class?

I've encountered an issue when testing my code.
void Library::checkOutBook(std::string pID, std::string bID); {
bool patronIDMatch = false, bookIDMatch = false;
int bookOnFile=-1, patronOnFile=-1;
for (int i=0; i<members.size(); i++) {
if (pID==members[i].getIdNum()) {
patronIDMatch=true;
patronOnFile=i;
break;
}
else continue;
for the first line here, I'm getting the following errors:
Library.cpp:68: error: prototype for ‘void Library::checkOutBook(std::string, std::string)’ does not match any in class ‘Library’
Library.cpp:68: error: expected unqualified-id before ‘{’ token
But I'm matching it as it appears in my Library class as such
//Library.hpp
#ifndef LIBRARY_HPP
#define LIBRARY_HPP
#include <string>
#include <vector>
#include "Patron.hpp"
class Library {
private:
std::vector<Book*> holdings;
std::vector<Patron*> members;
int currentDate;
public:
Library();
void addBook(Book*);
void addPatron(Patron*);
std::string checkOutBook(std::string pID, std::string bID);
std::string returnBook(std::string bID);
std::string requestBook(std::string pID, std::string bID);
std::string payFine(std::string pID, double payment);
void incrementCurrentDate();
Patron* getPatron(std::string pID);
Book* getBook(std::string bID);
};
#endif
How would I go about fixing this?
i am prohibited from altering the header file unfortunately :(
edit:
void Library::returnBook(std::string bID); {
bool bookIDMatch=false;
string tempPatronID;
int bookOnFile=-1;
for (int i=0; i
It doesn't match because the function you're trying to define returns void:
void Library::checkOutBook(std::string pID, std::string bID)
but the declaration in the Library class says it returns std::string:
std::string checkOutBook(std::string pID, std::string bID);
Also, remove that semicolon between the ) and the { in the function header.

No member named 'name' in namespace 'namespace'

I can't for the life of me figure out why this error is being generated as I'm pretty sure the syntax is correct (obviously I'm wrong!). So I figured I'd see if anyone here could point it out for me.
main.cpp
#include "Object.h"
int main(){
out = json::readJSON(data_dir + "a2-empty_array_with_empty_object.json", e, debug);
}
Object.h
namespace json{
template<typename T>
std::string readJSON(std::string jsonFile, T& object, bool debug = false, char delimiter = ',') {}
}
I'm basically getting this error, when clearly the function is in the namespace. Why does it refer to the function as a member? Maybe there is something else going on here...
Error:
a2main.cpp:66:21: error: no member named 'readJSON' in namespace 'json'
out = json::readJSON(data_dir + "a2-cartoons.json", c, debug, '|');
You are probably not including the header files correctly.
The following code compiles (with both clang and gcc) and runs fine
#include <string>
namespace json
{
template<typename T>
std::string readJSON(std::string jsonFile, T& object, bool debug = false, char delimiter = ',')
{
return "Hello"; //This function should return a string
}
}
int main()
{
std::string data_dir = "test-";
int e = 3;
bool debug = false;
std::string out = json::readJSON(data_dir + "a2-empty_array_with_empty_object.json", e, debug);
return 0;
}
I hope this helps.

mem_fun_ref: unresolved overloaded function type

The following code won't compile because of "error: no matching function for call to ‘mem_fun_ref()’" (gcc version 4.4.6).
#include <vector>
#include <string>
#include <string.h>
#include <algorithm>
#include <iostream>
using namespace std;
class toto
{
char v[10];
public:
toto(char* t) { memcpy(v, t, 9); }
bool test(const char* var) const { return !strncmp(var, v, 9); }
bool test(const string& var) const { return test(var.c_str()); }
};
int main()
{
vector<toto> t;
t.push_back("1");
t.push_back("2");
string name("2");
vector<toto>::iterator it = remove_if(t.begin(), t.end(),
bind2nd(mem_fun_ref(&toto::test), name)); // <= error
t.erase(it, t.end());
return 0;
}
I found a workaround: creating a
bool testZ(const string& var) const { return testZ(var); }
But I can't seem to find the correct template parameters, if that's even possible, to give to mem_fun_ref (or bind2nd?) to make it compile without my workaround.
Is there anyway to achieve this without my workaround, or is the workaround the "preferred" method?
You should be able to cast it according to C++ overloaded method pointer:
bind2nd(mem_fun_ref((bool (toto::*)(const string&) const) &toto::test), name));

Mixing template functions with classes

I'm creating a small logging class that allows a printf-like syntax (courtesy boost::format) using template functions to implement variable-length parameter lists. I think I'm close: after instantiating a Log object 'logger', I want to be able to write logger.Print("This %s is a %s", some_obj, another_obj);. The way I currently have it, this produces the error "No member named 'Print' in 'Log'".
Can anyone suggest what I need to change?
Log.h:
#ifndef LOG_H
#define LOG_H
#include <string>
using std::string;
#include <sstream>
#include <ostream>
#include <fstream>
#include <boost/format.hpp>
enum Severity {
DEBUG,
INFO,
WARN,
CRIT,
DIE,
LEVELS // always last; holds # of severity levels
};
class Log {
public:
Log();
Log(const char*, const char*);
void Print_r(int, const boost::format& );
private:
static const char * sev_code[];
// order is important here!
std::ofstream output_file_stream; // this must be initialized ..
std::ostream& output_stream; // .. before this is bound.
};
int LEVEL; // (where does this belong?)
// This unpacks the variadic arguments one at a time recursively
template <typename T, typename... Params>
void Print_r (int severity, boost::format &boost_format, const T &arg, const Params&... parameters) {
Print_r(severity, boost_format % arg, parameters...); // recursively unpack
}
// This checks severity and converts pat to boost::format
template <typename... Params>
void Print (int severity, const string &pat, const Params&... parameters) {
if (severity < LEVEL) return;
boost::format boost_format(pat);
Print_r(severity, boost_format, parameters...);
}
#endif
Log.cpp:
#include "Log.h"
#include <iostream>
using std::cout;
using std::endl;
#include <string>
using std::string;
#include <fstream>
const char * Log::sev_code[] = {
"DBUG",
"INFO",
"WARN",
"CRIT",
"DIE "
};
// Constructor w/no parms = logging to cout
Log::Log() :
output_stream(cout) {
}
// Constructor w/parms = logging to file
Log::Log(const char* dir, const char* file) :
output_stream(output_file_stream) {
string output_file_name = string(dir) + "/" + string(file);
output_file_stream.open(output_file_name.c_str(), std::ofstream::out);
}
// This does the actual logging of the formatted message to the
// output_stream:
void
Log::Print_r (int severity, const boost::format &boost_format) {
std::stringstream s;
s << "[" << sev_code[severity] << "] "
<< boost_format;
output_stream << s << endl;
}
From this code the Print template is outside of the Log class. You need to move it inside the class definition.