compile libfacebookcpp on linux , 'StringBuilder' was not declared - c++

when compile, it occurs an error:
PagingInfo.hpp:35: error: ‘StringBuilder’ was not declared in this scope.
I have inlude the right head file, but why compiler can not find the difinition of StringBuilder?
Utils.hpp:
#ifndef LIBFACEBOOKCPP_UTILS_H_
#define LIBFACEBOOKCPP_UTILS_H_
template<class TData, class TStr>
inline TData fromString(const TStr &str)
{
std::stringstream oss;
oss << str;
TData t;
oss >> t;
return t;
}
class StringBuilder
{
public:
inline operator const std::string () const
{
return oss.str();
}
private:
std::ostringstream oss;
};
#endif // LIBFACEBOOKCPP_UTILS_H_
PagingInfo.hpp
#ifndef LIBFACEBOOKCPP_PAGING_INFO_H_
#define LIBFACEBOOKCPP_PAGING_INFO_H_
#include "Utils.hpp"
namespace LibFacebookCpp
{
struct PagingInfo
{
PagingInfo(unsigned int offset_, unsigned int limit_) : offset(offset_), limit(limit_) { }
bool IsValid() const { return 0 != limit; }
void GetUri(Uri *uri) const
{
LIBFACEBOOKCPP_ASSERT(uri);
uri->query_params["limit"] = StringBuilder() << offset;
uri->query_params["offset"] = StringBuilder() << limit;
}
...
};
} // namespace LibFacebookCpp
#endif // LIBFACEBOOKCPP_PAGING_INFO_H_

When I add enough skeleton code to get this down to just your issue in ideone, I get a different error:
prog.cpp: error: no match for 'operator<<' in 'StringBuilder() << ((const LibFacebookCpp::PagingInfo*)this)->LibFacebookCpp::PagingInfo::offset'
Your StringBuilder class does not have a << operator defined. In order to use:
StringBuilder() << offset;
You will need to define one.
Between you and me, there are about 15 overloads of that operator for stringstreams (one for every primitive type). It would be a massive waste of time to reimplement all of them. Just use a stringstream.

Related

How do i read/write JSON with c++?

I would like to know how to read/write a JSON file using C++.
I will be using this file to store player info & setting for a simple game I'm making.
It's nothing fancy, just a console number guessing game, but I just use it to learn stuff.
I have to know how to read & write specific parts of a JSON.
Using a library, it can be done quite easily:
#include <nlohmann/json.hpp>
#include <iostream>
int main() {
// read file
auto json = nlohmann::json::parse("{\"value1\": \"string\"}");
// mutate the json
json["value1"] = "new string";
// write to a stream, or the same file
std::cout << json; // print the json
}
C++ don't have the built-ins for dealing with json. You can implement your own json data structure, or use one available like nlohmann/json or simdjson
You could create your own parser using pure C++ with the standard library only, but I would advise against.
Using struct_mapping it can be done:
#include "struct_mapping/struct_mapping.h"
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
struct Planet
{
std::string name;
double mass;
bool populated;
};
int main()
{
struct_mapping::reg(&Planet::name, "name");
struct_mapping::reg(&Planet::mass, "mass");
struct_mapping::reg(&Planet::populated, "populated");
Planet planet;
auto stream = std::ifstream("planet.json");
struct_mapping::map_json_to_struct(planet, stream);
planet.name = "Mars";
planet.populated = false;
std::ostringstream out_json_data;
struct_mapping::map_struct_to_json(planet, out_json_data, " ");
std::cout << out_json_data.str() << std::endl;
}
Data file example
{
"name": "Earth",
"mass": 1234,
"populated": true
}
I wrapped boost property tree initialized around classes and macros and it's close to type reflection(but it's still missing a reflection library to finish it off).
It Also supports nesting of types something that alot of so called "fantastic json" libraries fall short of when you get into
the nitty gritty.
So say you have a class what you want to serialize or deserialize in JSON:
I'd write in my cpp
class MyClass: public virtual Algorithm::Interface::ISimpleSerializedType
{
public:
int a;
string b;
// could be simplified further via a variadic macro to generate //SimplePropertyTree
virtual Algorithm::Interface::IPropertyTree SimplePropertyTree(Algorithm::Interface::IPropertyTree& pt, bool toPropertyTree)
{
PSER(a, int)
PSER(b, string)
}
};
The JSON would look something like
{
a : "1"
b :"somestring"
}
My read and write unit tests/snippets would look like this:
//write
MyClass entity;
entity.a = 1;
entity.filename = "test.json";
entity.ToFile();
// read
MyClass entity;
entity.filename = "test.json";
entity.FromFile(); // everything is loaded
code for Algorithm::Interface::ISimpleSerializedType
#ifndef I_SIMPLE_SERIALIZED_TYPE_H
#define I_SIMPLE_SERIALIZED_TYPE_H
#include "IType.h"
#include "IFileSerializer.h"
namespace Algorithm
{
namespace Interface
{
// Class contract that exposes common methods for which to extend
class ISimpleSerializedType : public virtual IType,public virtual IFileSerializer
{
public:
virtual IPropertyTree ToPropertyTree(void){
IPropertyTree pt;
return SimplePropertyTree(pt,true);
};
// method which extracts the values from property tree
virtual void FromPropertyTree(IPropertyTree& pt){
auto tree = SimplePropertyTree(pt,false);
pt = tree._pt;
};
protected:
// need to implement this
virtual IPropertyTree SimplePropertyTree(IPropertyTree& pt,bool ToPropertyTree)
{
return pt;
}
};
}
}
#endif
Code For ITYPE
#ifndef ITYPE_H
#define ITYPE_H
#include <sstream>
#include <string>
#include <vector>
#include <string>
#include "IPropertyTree.h"
#include <fstream>
// macross to simplify streaming property tree
#define __str__(s) #s
#define PADD(s) {\
try\
{\
std::string ss = std::to_string(s);\
std::string key = std::string(__str__(s));\
pt.add(key,ss);\
}\
catch (std::exception ex)\
{\
}\
}
#define PADDS(s) {\
try\
{\
std::string key = std::string(__str__(s));\
pt.add(key,s);\
}\
catch (std::exception ex)\
{\
}\
}
#define PADDBASE(BASE){\
auto st = std::string(__str__(BASE));\
auto pt2 = BASE##ToPropertyTree();\
pt.addPropertyTree(st, pt2);\
}
#define PADDMEMBER(membervar) {\
auto st = std::string(__str__(membervar));\
LOGIT1(st)\
auto _pt = membervar.ToPropertyTree();\
pt.addPropertyTree(st, _pt);\
}
// PGET
#define PGET(VAR,type) { std::string s(__str__(VAR));\
VAR = pt.get<type>(s); }
#define PGETBASE(VAR) {\
try\
{\
auto st = std::string(__str__(VAR));\
auto ptBase##VAR = pt.getChild(st); \
VAR##FromPropertyTree(ptBase##VAR);\
}\
catch (...)\
{\
}\
}
#define PGETMEMBER(membervar) {\
auto st = std::string(__str__(membervar));\
auto pt2 = pt.getChild(st);\
membervar.FromPropertyTree(pt2);\
}
///////////////
/// PGET2
#define PGET2(VAR,type) { std::string s(__str__(VAR));\
VAR = pt._pt.get<type>(s); }
#define PGET2BASE(VAR) {\
try\
{\
auto st = std::string(__str__(VAR));\
auto ptBase##VAR = pt._pt.getChild(st); \
VAR##FromPropertyTree(ptBase##VAR);\
}\
catch (...)\
{\
}\
}
#define PGET2MEMBER(membervar) {\
auto st = std::string(__str__(membervar));\
auto pt2 = pt_pt.getChild(st);\
membervar.FromPropertyTree(pt2);\
}
// PSerialize uses a implied type bool ToPropertyTree and pt
#define PSER(VAR,type) if(toPropertyTree) {\
std::cout << "padd" << std::endl;\
PADD(VAR)\
} else {\
std::cout << "pget" << std::endl;\
PGET(VAR,type)\
}
#define PSERS(VAR) if(toPropertyTree) {\
PADDS(VAR)\
} else {\
PGET(VAR,std::string)\
}
#define PSERBASE(VAR)if(toPropertyTree) {\
PADDBASE(VAR)\
} else {\
PGET2BASE(VAR)\
}
#define PSERMEMBER(membervar)if(toPropertyTree) {\
PADDMEMBER(membervar) \
} else {\
PGET2MEMBER(membervar) \
}
namespace Algorithm
{
namespace Interface
{
// Class contract that exposes common methods for which to extend
class IType
{
public:
IType() {};
// causes problems with hiberlite when you derive it
// from MVC so omitting this
// IType(IType& rhs) { *this = rhs; }
virtual ~IType(){}; // destructor
// methods don't communicate tho the key just the value
// like stl containers returns size of type
virtual size_t size(void){ return sizeof(IType);};
// says the maximum size of the type
virtual size_t max_size(void) { return sizeof(IType); };
virtual void ToString(char* data,size_t& dataSize){ /* not implemented*/ };
virtual void FromString(char* data,size_t& dataSize){};
IType& operator=(const IType& rhs){
std::string s;
IType& rhsRef = const_cast<IType&>(rhs);
size_t size = rhsRef.size();
s.resize(size);
rhsRef.ToString(const_cast<char*>(s.c_str()), size);
FromString(const_cast<char*>(s.c_str()),size);
return *this;
};
// must be friended methods
// istream extraction operators terminated by std::endl for each respective subtype
// ostream extraction operators terminated by std::endl for each respective subtype
// encode the stream to stream with variable name + value name. Useful for key value streams;
virtual IPropertyTree ToPropertyTree(void){
IPropertyTree pt;
return pt;
};
// method which extracts the values from property tree
virtual void FromPropertyTree(boost::property_tree::ptree& typesEncodedInAPropertyTree){
IPropertyTree pt;
pt._pt = typesEncodedInAPropertyTree;
FromPropertyTree(pt);
};
// method which extracts the values from property tree
virtual void FromPropertyTree(IPropertyTree& typesEncodedInAPropertyTree) {
};
// call a serializer here
// method instructs how to write to file by calling the approppriate serializer
virtual void ToFile(void){
};
virtual void FromFile(void) {};
virtual std::string TypeName(void) { return ""; };
protected:
inline bool exist(const std::string& name)
{
std::ifstream file(name);
if (!file) // If the file was not found, then file is 0, i.e. !file=1 or true.
return false; // The file was not found.
else // If the file was found, then file is non-0.
return true; // The file was found.
}
};
}
}
#endif
Code For IPropertyTree
#ifndef I_PROPERTY_TREE_H
#define I_PROPERTY_TREE_H
#include <boost/property_tree/ptree.hpp>
#include <memory>
#include <map>
#include <string>
#include <vector>
#include <iostream>
namespace Algorithm
{
namespace Interface
{
class IPropertyTree
{
const std::string attributePrefix = ".<xmlattr>."; // attribute prefix to reference a attribute within boost property tree
// https://stackoverflow.com/questions/3690436/how-are-attributes-parsed-in-boost-propertytree
std::string BuildAttributeInsertionKey(std::string& key, std::string& attributeKey) { return key + attributePrefix + attributeKey; };
public:
boost::property_tree::ptree _pt; // good reference reading https://theboostcpplibraries.com/boost.propertytree
const IPropertyTree& operator=(const IPropertyTree& pt){
this->_pt = pt._pt;
return *this;};
IPropertyTree(void) :_pt() {};
IPropertyTree(boost::property_tree::ptree& pt) : _pt(pt) {};
// usually only accessed by the serializers don't manually edit this
boost::property_tree::ptree& GetBoostPropertyTree(void) { return _pt; };
#ifdef _WIN32
// key/value get and set
template <class T>
void add(std::string& key, T& value)
{
_pt.put(key, value);
};
#else
template <class T>
void add(std::string key, T value)
{
_pt.put(key, value);
};
#endif
template <class T>
T get(std::string& path) {
return _pt.get<T>(path);
};
// attribute get/set
template <class T>
void addAttribute(std::string& keyName, std::string& attributeKey, T& attributeValue) {
_pt.add(BuildAttributeInsertionKey(keyName, attributeKey), std::to_string(attributeValue));
}
IPropertyTree getChild(std::string& key)
{
return IPropertyTree(_pt.get_child(key));
}
template <class T>
T getAttribute(std::string& keyPath, std::string& attributeName) {
return _pt.get<T>(BuildAttributeInsertionKey(keyPath, attributeName));
}
void addPropertyTree(std::string& keyOfChildTree,IPropertyTree& tree)
{
_pt.add_child(keyOfChildTree,tree.GetBoostPropertyTree());
};
void addAttribute(std::string& keyName,std::string& attributeKey, std::string& attributeValue)
{
_pt.add(BuildAttributeInsertionKey(keyName,attributeKey), attributeValue);
};
};
}
}
#endif
Code For IFileSerializer
#ifndef I_FILE_SERIALIZER_H
#define I_FILE_SERIALIZER_H
#include "IJSONSerialize.h"
#include "IType.h"
#include "../../Tools/Diagnostics/Logger/Logger.h" // this uses LOGIT but you can just replace with std::cout
#include <cstdint>
#include <cstdlib>
#include <string>
namespace Algorithm
{
namespace Interface
{
class IFileSerializer;
// a Serializer for JSON
class IFileSerializer : public virtual Algorithm::Interface::IType
{
public:
std::string filename;
IFileSerializer(void):Algorithm::Interface::IType(),filename(){};
virtual void ToFile(void)
{
std::string msg = TypeName() + "::ToFile()";
LOGIT1(msg)
std::string testJSON(filename);
auto pt = ToPropertyTree();
msg = TypeName() + "::ToFile() calling IJSON serialize";
LOGIT1(msg)
Algorithm::Interface::IJSONSerialize test(testJSON, pt);
msg = TypeName() + "::ToFile() WriteFile";
LOGIT1(msg)
test.WriteFile();
};
virtual void FromFile(void)
{
auto msg = TypeName() + "::FromFile()\n";
LOGIT1(msg)
std::string testJSON(filename);
auto pt = ToPropertyTree();
Algorithm::Interface::IJSONSerialize test(testJSON, pt);
test.ReadFile();
this->FromPropertyTree(test.GetPropertyTree());
};
virtual Algorithm::Interface::IPropertyTree ToPropertyTree(void) { Algorithm::Interface::IPropertyTree pt; return pt;};
// method which extracts the values from property tree
virtual void FromPropertyTree(Algorithm::Interface::IPropertyTree& pt) {};
void ParseServerArgs(char** argv, int argc){
std::string msg2="IFileSerializer::ParseServerArgs";
LOGIT1(msg2)
filename = "config.json";
if(exist(filename))
{
std::string msg = "IFileSerializer::Calling FromFile";
LOGIT1(msg)
FromFile();
}
else
{
std::string msg = "IFileSerializer::Calling ToFile";
LOGIT1(msg)
ToFile(); // write it back so next time you can feed in the json
}
};
}; // end class
}
}
#endif
IJSONSerialize Code
#ifndef IJSONSERIALIZE_H
#define IJSONSERIALIZE_H
#include <string>
#include <vector>
#include <iostream>
#include <boost/property_tree/json_parser.hpp>
#include "IPropertyTree.h"
namespace Algorithm
{
namespace Interface
{
// object that provides facilities to serialize JavaScript Object Notation(JSON)
// citation: https://stackoverflow.com/questions/4586768/how-to-iterate-a-boost-property-tree
class IJSONSerialize
{
IPropertyTree _pt;
std::string _filename;
public:
IJSONSerialize(const std::string& filename, IPropertyTree& pt):_pt(pt),_filename(filename){
};
virtual void WriteFile(void){
try
{
boost::property_tree::json_parser::write_json(_filename, _pt.GetBoostPropertyTree());
}
catch(std::exception ex)
{
std::cerr << "can't write json file " << _filename;
}
};
virtual void WriteAsAString(std::string& outString)
{
std::stringstream ss;
boost::property_tree::write_json(ss, _pt.GetBoostPropertyTree());
outString = ss.str();
};
virtual void ReadFile(void){
try
{
boost::property_tree::read_json(_filename, _pt.GetBoostPropertyTree());
}
catch(const boost::property_tree::json_parser_error &jpe)
{
//do error handling
std::cerr << "can't read json file " << _filename <<jpe.what();
}
};
virtual void ReadFromString(std::string& s){
try
{
std::stringstream ss;
ss << s;
auto pt = _pt.GetBoostPropertyTree(); boost::property_tree::json_parser::read_json(ss, pt);
}
catch(std::exception)
{
}
};
virtual std::string WriteToString(void){
std::stringstream ss;
boost::property_tree::json_parser::write_json(ss,_pt.GetBoostPropertyTree());
return ss.str();
};
// use to retrieve all the values but
virtual IPropertyTree& GetPropertyTree(void){
return _pt;
};
};
}
}
#endif
If any code missing you can find it in my bitbucket crossplatform C++ network template that's built
on top of boost asio. The code is here: https://bitbucket.org/ptroen/crossplatformnetwork/src/master/
And again if you missed the comment and don't want to use LOGIT you can just find and replace with std::cout
Note code above is working but if you study enough their is some tech debt that could be optimized even more like reflection
Anyways hope you find this useful

C++ Cereal save/load_and_construct not working

So I'm trying to use the Cereal library and I've come to an issue I can't seem to overcome. Essentially the doc's say it is possible to deserialize Types with no default constructor. Yet in the implementation notes it says Define a serialize or save/load pair as you normally would yet the serialize/load options cannot be defined in a valid manner if there is no default constructor. I take this to mean, the load_and_construct function takes the place of load. Yet when implementing a relatively simple example seen below.
"main.cpp"
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <memory>
#include <cereal/access.hpp>
#include <cereal/types/string.hpp>
#include <cereal/types/vector.hpp>
#include <cereal/types/memory.hpp>
#include <cereal/archives/portable_binary.hpp>
struct string_wrapper {
const std::string str;
string_wrapper(const std::string& _a) : str{_a} {}
template <class Archive>
void save(Archive& _archive) const {
_archive(str);
}
template <class Archive>
static void load_and_construct(Archive& _archive,
cereal::construct<string_wrapper>& _construct) {
std::string a;
_archive(a);
_construct(a);
}
};
struct wrapper_of_string_wrappers {
const std::vector<string_wrapper> strs;
wrapper_of_string_wrappers(
const std::vector<string_wrapper>& _a
) : strs{_a} { }
template <class Archive>
void save(Archive& _archive) const {
_archive(strs);
}
template <class Archive>
static void load_and_construct(Archive& _archive,
cereal::construct<wrapper_of_string_wrappers>& _construct) {
std::vector<string_wrapper> strs;
_archive(strs);
_construct(strs);
}
};
int main() {
auto file = "test.bin";
{ // save
std::ofstream os(file, std::ios::binary);
cereal::PortableBinaryOutputArchive archiveSave(os);
std::vector<string_wrapper> as;
as.push_back({"Hello"});
as.push_back({"World"});
wrapper_of_string_wrappers test(as);
auto test_ptr = std::make_unique<wrapper_of_string_wrappers>(test);
archiveSave(test_ptr);
}
{ // load
std::ifstream is(file, std::ios::binary);
cereal::PortableBinaryInputArchive archiveLoad(is);
std::unique_ptr<wrapper_of_string_wrappers> test = nullptr;
archiveLoad(test);
std::cout << (*test).strs[0].str << " " << (*test).strs[1].str << std::endl;
}
std::cin.get();
return 0;
}
This code obviously is kind of pointless, its just a minimal example to illustrate the problem I'm running into.
From this page
Non-default constructors are currently only supported for serializing pointers
Your problem here is you are trying to serialize non pointer values with no default constructor here
std::vector<string_wrapper> strs;
_archive(strs);
To solve your problem you need either make default constructor for string_wrapper with save/load pair or use string_wrapper as pointer in wrapper_of_string_wrappers.
Here is working code for second option(string_wrapper remains same):
struct wrapper_of_string_wrappers {
//const std::vector<std::unique_ptr<string_wrapper>> strs;
//const string_wrapper strs;
const std::unique_ptr<string_wrapper> strs;
wrapper_of_string_wrappers(
//const std::vector<std::unique_ptr<string_wrapper>>& _a
const string_wrapper _a
) : strs{ new string_wrapper(_a) } { }
wrapper_of_string_wrappers(
const wrapper_of_string_wrappers& w
) : strs{ new string_wrapper(*w.strs) } { }
template <class Archive>
void save(Archive& _archive) const {
_archive(strs);
}
template <class Archive>
static void load_and_construct(Archive& _archive,
cereal::construct<wrapper_of_string_wrappers>& _construct) {
//std::vector<std::unique_ptr<string_wrapper>> strs;
std::unique_ptr<string_wrapper> strs;
_archive(strs);
_construct(*strs);
}
};
int main() {
auto file = "test.bin";
{ // save
std::ofstream os(file, std::ios::binary);
cereal::PortableBinaryOutputArchive archiveSave(os);
string_wrapper as("Hello");
wrapper_of_string_wrappers test(as);
auto test_ptr = std::make_unique<wrapper_of_string_wrappers>(test);
archiveSave(test_ptr);
}
{ // load
std::ifstream is(file, std::ios::binary);
cereal::PortableBinaryInputArchive archiveLoad(is);
std::unique_ptr<wrapper_of_string_wrappers> test = nullptr;
archiveLoad(test);
std::cout << (*test).strs->str << std::endl;
}
std::cin.get();
return 0;
}

C++ invalid use of non-static data member [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I have looked at other questions regarding this error, but I so far have not found what looked like the answer to my problem there. I have two classes Message and ColorString. In a method of the former I make several instances of the latter by passing members of Message to the constructor of ColorString
message.hpp
#ifndef __MESSAGE__HPP
#define __MESSAGE__HPP
#if defined __linux || defined __APPLE__
#define UNIXLIKE
#endif
////////////////////////////////////////////////////////////////////////////////
// Message helps organize error and warning messages //
////////////////////////////////////////////////////////////////////////////////
#include <iostream>
#include <sstream>
#include <fstream>
#include "color.hpp"
////////////////////////////////////////////////////////////////////////////////
// MESSSAGE //
////////////////////////////////////////////////////////////////////////////////
class Message
{
////////////////////////////////////////////////////////////////////////////////
public: // types
////////////////////////////////////////////////////////////////////////////////
typedef COLOR::ColorString colstr;
typedef COLOR::ColorID color;
////////////////////////////////////////////////////////////////////////////////
public: // methods
////////////////////////////////////////////////////////////////////////////////
Message(std::ostream& o = std::cerr)
: o(std::cerr)
{
}
////////////////////////////////////////////////////////////////////////////////
Message(const std::string& message,
const std::string& label ="",
const std::string file="",
const int line = -1,
std::ostream& o = std::cerr,
const color c = COLOR::RED
)
: o(std::cerr)
{
}
////////////////////////////////////////////////////////////////////////////////
friend std::ostream& operator<<(std::ostream& o, Message& m)
{
#ifdef UNIXLIKE
colstr lbl(label, c);
colstr msg(message);
colstr ln(linestr);
colstr fl(file);
#else
std::string lbl(label);
std::string msg(message);
std::string ln(linestr);
std::string fl(file);
#endif
o << fl << ln;
if (fl.size() > 0 || ln.size() > 0) o << ": ";
o << lbl << " " << msg << "\n";
o.flush();
return o;
}
////////////////////////////////////////////////////////////////////////////////
private: // methods
////////////////////////////////////////////////////////////////////////////////
void init(const std::string& message,
const std::string& label = "",
const std::string file="",
const int line = -1,
std::ostream& o = std::cerr,
const color c = COLOR::RED)
{
this->message = message;
this->label = label;
this->file = file;
this->line = line;
this->c = c;
if (this->line > -1)
{
std::stringstream ss;
ss << this->line;
ss >> linestr;
}
if (this->file.size() > 0)
{
this->file = this->file+":";
if (this->line > -1)
{
this->file = this->file+linestr; linestr="";
}
}
}
////////////////////////////////////////////////////////////////////////////////
private : // fields
////////////////////////////////////////////////////////////////////////////////
std::string label;
std::string message;
std::string file;
int line;
std::ostream& o;
color c;
std::string linestr;
};
#endif
The constructor of ColorString looks like this:
/**
* #brief constructs a ColorString with color #p c and the string
* #p s.
* #param s string to wrap
* #param c color to print #p s in
* #param bold determines whether #p s will be printed bold
*/
ColorString(str s, ColorID c=DEF, bool bold=1)
:string(s),
color(c),
bold(bold)
{
}
The part causing the errors is this:
#ifdef UNIXLIKE
colstr lbl(label, c);
colstr msg(message);
colstr ln(linestr);
colstr fl(file);
#else
Errors:
message.hpp:58:20: error: invalid use of non-static data member 'label'
colstr lbl(label, c);
^~~~~
message.hpp:58:27: error: invalid use of non-static data member 'c'
colstr lbl(label, c);
^
message.hpp:59:20: error: invalid use of non-static data member 'message'
colstr msg(message);
^~~~~~~
message.hpp:60:19: error: invalid use of non-static data member 'linestr'
colstr ln(linestr);
^~~~~~~
message.hpp:61:19: error: invalid use of non-static data member 'file'
colstr fl(file);
What's the problem here?
The problem is that you are defining a friend function. Even when you define them "inline" in the class, they are still non-member functions and need an object instance to access their members.
You need to do e.g.
colstr lbl(m.label, m.c);

error: no matching function for call to ‘to_string(std::basic_string<char>&)’

Even though in a template I can have any type, the function to_string does not work on basic strings:
for example:
std::string str("my string");
my_class(str);
with this functor definition:
template<class valuetype>
void operator()(valuetype value)
{
...
private_string_field = std::to_string(value);
does not work. here is the error:
error: no matching function for call to
‘to_string(std::basic_string&)’
What is the best way to avoid it.
In advance, I request avoid linking to irrelevant questions just because of a few common keywords.
std::to_string only works on fundamental numeric types.
If you need a more generic function, boost::lexical_cast will work on many more types - effectively any type that can be sent to an iostream.
#include <boost/lexical_cast.hpp>
...
private_string_field = boost::lexical_cast<std::string>(value);
There is no to_string for basic string. It would have nothing to do.
After Benjamin Lindley's suggestion I would consider the following design, use to_string but provide default template:
#include <iostream>
#include <string>
struct Type {
explicit operator std::string() const{
return std::string("I am type");
}
};
namespace std {
template <typename T>
string to_string(const T& value) {
return string(value);
}
}
int main(int argc, char **argv) {
// this is what would be in class
Type x;
std::string private_string_field;
private_string_field = std::to_string(42);
std::cout << private_string_field << std::endl;
private_string_field = std::to_string(x);
std::cout << private_string_field << std::endl;
return 0;
}
By default it tries to cast the operand to a string. This way custom types can provide their own conversion. Alternative design would be to internally use stringstream and operator<< for conversions, like this:
#include <iostream>
#include <string>
#include <sstream>
struct Type {
friend std::ostream& operator<<(std::ostream& out, const Type& value){
return out << "Type through operator<<";
}
};
template <class T>
std::string to_str(const T& value) {
std::string ret;
std::ostringstream ss;
ss << value;
ret = ss.str();
return ret;
};
int main(int argc, char **argv) {
// this is what would be in class
Type x;
std::string private_string_field;
private_string_field = to_str(42);
std::cout << private_string_field << std::endl;
private_string_field = to_str(x);
std::cout << private_string_field << std::endl;
return 0;
}

Enum in constructor Qt C++

I'm create my own LOGGER, where I use an additional class for overload macro.
There is #define qlcd MacroCall(QLC::Debug), so i can use logger like this: qlcd << message;
It's ok, but when i try use qlcd("log name") i got an error. Look minimal code (no macro for simplify):
#include <QVariant>
#include <QDebug>
class QLC
{
public:
// Error types
enum LevelType{
Debug=0, // Debug
Error=1, // Error
WTF = 2 // WTF???
} level;
QString logger;
// Constructors
QLC(QLC::LevelType l)
:level(l), logger(":")
{}
QLC(QLC::LevelType l, QString log)
:level(l), logger(log)
{}
// OPERATOR <<
QLC& operator<<(const QVariant var){
qDebug() << "(" + QString::number(level) + ")" << logger << var;
}
};
class MacroCall
{
QLC::LevelType level;
public:
MacroCall()
:level(QLC::Debug){}
MacroCall(int i)
:level(QLC::WTF){}
MacroCall(QLC::LevelType l)
:level(l){}
QLC operator()(){
return QLC(level);
}
QLC operator()(QString log){
return QLC(level, log);
}
};
int main(int argc, char*argv[])
{
MacroCall()("WorkLog") << "No level, yes logname";
MacroCall(QLC::Error)() << "No logname, yes level";
MacroCall a(QLC::Error);
a("WorkLog") << "Logname and level at different lines";
// GET READY!
// INT as level and logname:
MacroCall(2)("WorkLog") << "WTF?? It works!";
//MacroCall(QLC::WTF)("NotWorkLog") << "It's not work!!!!!!";
// NOT WORK: error: invalid use of qualified-name 'QLC::WTF'
// Qt 4.8.3
return 0;
}
The code
MacroCall(QLC::WTF)("NotWorkLog")
is interpreted as declaration of a variable:
MacroCall QLC::WTF("NotWorkLog")
Example:
class A
{
public:
enum E {
x=1
};
public:
A(E) {}
void operator()(int) const { }
};
class B {};
void f()
{
(A(A::x))(1); // Ok
A{A::x}(1); // Ok
A(a)(A::x); // Ok
A::E a; // ‘a’ has a previous declaration as ‘A a’
A(A::x)(1); // invalid use of qualified-name ‘A::x’
B(b)(A::x); // no matching function for call to ‘B::B(A::E)’
}
The code you gave compiles (except that the method QLC& operator<<(const QVariant var) has to return something), eventhough I'm not sure of how it's supposed to be used.
My guess is that your 2 classes are defined in different headers and an include is missing. Does Macrocall header include QLC header ?