Mixing template functions with classes - c++

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.

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

CRTP with unique_ptr causes segfault

I'm using CRTP design pattern to implement logging mechanism for my project. Base CRTP class looks like this:
#include <fstream>
#include <memory>
#include <mutex>
#include <iostream>
#include <sstream>
template <typename LogPolicy>
class Logger
{
public:
template <typename... Args>
void operator()(Args... args)
{
loggingMutex.lock();
putTime();
print_impl(args...);
}
void setMaxLogFileSize(unsigned long maxLogFileSizeArg)
{
//if (dynamic_cast<FileLogPolicy *>(policy.get()))
// policy->setMaxLogFileSize(maxLogFileSizeArg);
}
~Logger()
{
print_impl(END_OF_LOGGING);
}
protected:
std::stringstream buffer;
std::mutex loggingMutex;
std::string d_time;
private:
static constexpr auto END_OF_LOGGING = "***END OF LOGGING***";
void putTime()
{
time_t raw_time;
time(&raw_time);
std::string localTime = ctime(&raw_time);
localTime.erase(std::remove(localTime.begin(), localTime.end(), '\n'), localTime.end());
buffer << localTime;
}
template <typename First, typename... Rest>
void print_impl(First first, Rest... rest)
{
buffer << " " << first;
print_impl(rest...);
}
void print_impl()
{
static_cast<LogPolicy*>(this)->write(buffer.str());
buffer.str("");
}
};
One of the concrete logging class is logging to file, which looks like this:
#include "Logger.hpp"
class FileLogPolicy : public Logger<FileLogPolicy>
{
public:
FileLogPolicy(std::string fileName) : logFile(new std::ofstream)
{
logFile->open(fileName, std::ofstream::out | std::ofstream::binary);
if (logFile->is_open())
{
std::cout << "Opening stream with addr " << (logFile.get()) << std::endl;
}
}
void write(const std::string content)
{
std::cout << "Writing stream with addr " << (logFile.get()) << std::endl;
(*logFile) << " " << content << std::endl;
loggingMutex.unlock();
}
virtual ~FileLogPolicy()
{
}
private:
std::unique_ptr<std::ofstream> logFile; //Pointer to logging stream
static const char *const S_FILE_NAME; //File name used to store logging
size_t d_maxLogFileSize; //File max size used to store logging
};
Basically I create object of policy class and would like to log stuff, depending on the policy chosen. So for example I create logger like this:
FileLogPolicy log("log.txt");
In this case it should use Logger to save logs to file, by calling static_cast<LogPolicy*>(this)->write(buffer.str()). Apparently calling write function works fine but stream object is changing to null. How is that possible if FileLogPolicy destructor has not been called yet? When I change logFile to be normal pointer all works well. I don't get it where is the difference.
~Logger()
{
print_impl(END_OF_LOGGING);
}
this code runs after the descendend class has been destroyed.
void print_impl()
{
static_cast<LogPolicy*>(this)->write(buffer.str());
buffer.str("");
}
it then casts this to be a pointer to a class that this is no longer.
The unique ptr is gone, and even accessing the member is UB.

C++ SFML Gamedev Book - Unresolved External Symbol from ResourceHolder class

I have the following three files, of which I cannot find the source of an error that it is producing:
Main.cpp
#include <SFML/Graphics.hpp>
#include <iostream>
#include "ResourceHolder.h"
namespace Textures
{
enum ID { Landscape, Airplane, Missile };
}
int main()
{
//...
try
{
ResourceHolder<sf::Texture, Textures::ID> textures;
textures.load(Textures::Airplane, "Airplane.png");
}
catch (std::runtime_error& e)
{
std::cout << "Exception: " << e.what() << std::endl;
}
//...
}
ResourceHolder.h
#pragma once
#include <map>
#include <string>
#include <memory>
#include <stdexcept>
#include <cassert>
template <typename Resource, typename Identifier>
class ResourceHolder
{
public:
void load(Identifier id, const std::string& fileName);
Resource& get(Identifier id);
const Resource& get(Identifier id) const;
private:
void insertResource(Identifier id, std::unique_ptr<Resource> resource);
std::map<Identifier, std::unique_ptr<Resource>> mResourceMap;
};
ResourceHolder.cpp
#include "ResourceHolder.h"
template <typename Resource, typename Identifier>
void ResourceHolder<Resource, Identifier>::load(Identifier id, const std::string& fileName)
{
//Create and load resource
std::unique_ptr<Resource> resource(new Resource());
if (!resource->loadFromFile(fileName)) {
throw std::runtime_error("ResourceHolder::load - Failed to load " + fileName);
}
//If loading was successful, insert resource to map
insertResource(id, std::move(resource));
}
template <typename Resource, typename Identifier>
Resource& ResourceHolder<Resource, Identifier>::get(Identifier id)
{
auto found = mResourcemap.find(id);
assert(found != mResourceMap.end());
return *found->second();
}
template <typename Resource, typename Identifier>
void ResourceHolder<Resource, Identifier>::insertResource(Identifier id, std::unique_ptr<Resource> resource)
{
//Insert and check success
auto inserted = mResourceMap.insert(std::make_pair(id, std::move(resource)));
assert(inserted.second);
}
If I were to remove the try-catch combination in main.cpp, the code compiles fine; However, if I leave it there it gives me an LNK2019 (Unresolved external symbol) Error.
What is the source of this error, and how would I fix it?
You can't define templates inside .cpp files. They have to be defined in the header so the compiler can see the implementation and generate the specific classes.
Here's a better question/answer on why it is so Why can templates only be implemented in the header file?.
EDIT: What's wrong in the get function
Two things.
First is this auto found = mResourcemap.find(id);. Your map name is incorrect, m should be upper case -> mResourceMap.
Then the line return *found->second();. The map iterator contains a pair, and the first and second members are not functions but data members. You should write return *found->second;.
I would advise you to understand the structures you're working with before using templates. The compile errors with templates are pretty messy and harder to read. Also you could make a separate test program and make a resource manager with no templates to understand your errors more easily, then build the template on top of your working resource manager.
With all the other answers providing you with enough information to why your code don't compile and might not be valid, this is a resource manager i wrote for SFML some time ago, might be of use to you:
HPP FILE:
#ifndef RESOURCEMANAGER_HPP
#define RESOURCEMANAGER_HPP
/************ INCLUDES ***********/
#include <iostream>
#include <map>
#include <vector>
#include <string>
#include <memory>
#include "SFML/Graphics.hpp"
#include "SFML/Audio.hpp"
class ResourceManager
{
private:
std::map<std::string,std::unique_ptr<sf::Texture>> listImageContainer;
std::map<std::string,std::pair<std::unique_ptr<sf::SoundBuffer>,std::unique_ptr<sf::Sound>>> listSoundContainer;
std::map<std::string,std::unique_ptr<sf::Font>> listFontContainer;
public:
ResourceManager();
std::unique_ptr<sf::Sound>& LoadSound(const std::string);
std::unique_ptr<sf::Font>& LoadFont(const std::string);
std::unique_ptr<sf::Texture>& LoadImage(const std::string);
~ResourceManager();
};
#endif
CPP FILE:
#include "ResourceManager.hpp"
ResourceManager::ResourceManager()
{
}
std::unique_ptr<sf::Sound>& ResourceManager::LoadSound(const std::string _fileName)
{
if (listSoundContainer.find(_fileName) == listSoundContainer.end())
{
std::unique_ptr<sf::SoundBuffer> soundBuffer(new sf::SoundBuffer());
if (soundBuffer->loadFromFile("assets/sound/" + _fileName) != false)
{
std::unique_ptr<sf::Sound> sound(new sf::Sound(*soundBuffer));
listSoundContainer[_fileName] = std::make_pair(std::move(soundBuffer), std::move(sound));
return listSoundContainer[_fileName].second;
}
else
{
std::cerr << "Error loading sound..." << std::endl;
}
}
else
{
return listSoundContainer[_fileName].second;
}
}
std::unique_ptr<sf::Font>& ResourceManager::LoadFont(const std::string _fileName)
{
if (listFontContainer.find(_fileName) == listFontContainer.end())
{
std::unique_ptr<sf::Font> font(new sf::Font());
if (font->loadFromFile("assets/font/" + _fileName)!=false)
{
listFontContainer[_fileName] = std::move(font);
return listFontContainer[_fileName];
}
else
{
std::cerr << "Error loading font..." << std::endl;
}
}
else
{
return listFontContainer[_fileName];
}
}
std::unique_ptr<sf::Texture>& ResourceManager::LoadImage(const std::string _fileName)
{
if (listImageContainer.find(_fileName) == listImageContainer.end())
{
std::unique_ptr<sf::Texture> texture(new sf::Texture);
if (texture->loadFromFile("assets/image/" + _fileName)!=false)
{
listImageContainer[_fileName] = std::move(texture);
return listImageContainer[_fileName];
}
else
{
std::cerr << "Error loading image: " << _fileName << std::endl;
}
}
else
{
return listImageContainer[_fileName];
}
}
ResourceManager::~ResourceManager(){}
How to use:
ResourceManager resourceManager;
auto& sound = resourceManager.LoadSound("nice.wav");
auto& image = resourceManager.LoadImage("head.png");
auto& sound2 = resourceManager.LoadSound("nice.wav"); //<--- already loaded
sound.play();
etc...

how to convert single-byte string to wide string in c++?

I know the encoding and that the input string is 100% single byte, no fancy encodings like utf etc. And all I want is to convert it to wchar_t* or wstring basing on a known encoding. What functions to use ? btowc() and then loop ? Maybe string objects have something useful in them. There are lot of examples but all are for "multibyte" or fancy loops with btowc() that only show how to display output on screen that indeed this function is working, I haven't seen any serious example how to deal with buffers in such situation, is always wide char 2x larger than single char string ?
Try this template. It served me very well.
(author unknown)
/* string2wstring.h */
#pragma once
#include <string>
#include <vector>
#include <locale>
#include <functional>
#include <iostream>
// Put this class in your personal toolbox...
template<class E,
class T = std::char_traits<E>,
class A = std::allocator<E> >
class Widen : public std::unary_function<
const std::string&, std::basic_string<E, T, A> >
{
std::locale loc_;
const std::ctype<E>* pCType_;
// No copy-constructor, no assignment operator...
Widen(const Widen&);
Widen& operator= (const Widen&);
public:
// Constructor...
Widen(const std::locale& loc = std::locale()) : loc_(loc)
{
#if defined(_MSC_VER) && (_MSC_VER < 1300) // VC++ 6.0...
using namespace std;
pCType_ = &_USE(loc, ctype<E> );
#else
pCType_ = &std::use_facet<std::ctype<E> >(loc);
#endif
}
// Conversion...
std::basic_string<E, T, A> operator() (const std::string& str) const
{
typename std::basic_string<E, T, A>::size_type srcLen =
str.length();
const char* pSrcBeg = str.c_str();
std::vector<E> tmp(srcLen);
pCType_->widen(pSrcBeg, pSrcBeg + srcLen, &tmp[0]);
return std::basic_string<E, T, A>(&tmp[0], srcLen);
}
};
// How to use it...
int main()
{
Widen<wchar_t> to_wstring;
std::string s = "my test string";
std::wstring w = to_wstring(s);
std::wcout << w << L"\n";
}

Storing function pointer in std::function

I'm trying to write a C++0x wrapper around dlopen()/dlsym() to dynamically load functions from shared objects:
class DynamicLoader
{
public:
DynamicLoader(std::string const& filename);
template<class Signature>
std::function<Signature> load(std::string const& functionName);
private:
void *itsLibraryHandle;
};
DynamicLoader::DynamicLoader(std::string const& filename)
{
itsLibraryHandle = dlopen(filename.c_str(), RTLD_LAZY);
if(!itsLibraryHandle)
{ /* Throw Some Error */ }
}
template<class Signature>
std::function<Signature> DynamicLoader::load(std::string const& functionName)
{
return <insert magic here> dlsym(itsHandle, functionName.c_str());
}
Is there a way to convert the void* function pointer returned by dlsym into a std::function?
try this:
static_cast<Signature*>()
seems works in VC10
complete test:
#include <functional>
void test()
{}
template <typename Signature>
std::function<Signature> cast(void* f)
{
return static_cast<Signature*>(f);
}
int main()
{
std::function<void()> f = cast<void()>(&test);
return 0;
}
Based on what I see here: http://pubs.opengroup.org/onlinepubs/009695399/functions/dlsym.html
#include <boost/function_types/components.hpp>
#include <boost/function_types/function_pointer.hpp>
template< typename Signature >
std::function<Signature> DynamicLoader::load(std::string const& name)
{
namespace ft = boost::function_types;
typedef typename ft::function_pointer< typename ft::components<Signature>::type >::type fp_t;
fp_t fun_ptr;
*reinterpret_cast<void**>(&fun_ptr) = dlsym(itsHandle, name.c_str());
return fun_ptr;
}
I've never used dlsym so I don't understand why the cast is being done that way and not simply casting dlsym's return like so:
fun_ptr = reinterpret_cast<fp_t>(dlsym(itsHandle, name.c_str());
You just need to cast result of dlsym() call to a proper type. Here's a complete working example:
#include <functional>
#include <iostream>
#include <stdexcept>
#include <string>
#include <dlfcn.h>
class DynamicLoader
{
public:
DynamicLoader(std::string const& filename) :
m_handle(dlopen(filename.c_str(), RTLD_LAZY))
{
if (!m_handle)
{
throw std::logic_error("can't load library named \"" + filename + "\"");
}
}
template<class T>
std::function<T> load(std::string const& functionName) const
{
dlerror();
void* const result = dlsym(m_handle, functionName.c_str());
if (!result)
{
char* const error = dlerror();
if (error)
{
throw std::logic_error("can't find symbol named \"" + functionName + "\": " + error);
}
}
return reinterpret_cast<T*>(result);
}
private:
void* const m_handle;
};
int main()
{
DynamicLoader const loader("/lib64/libz.so.1");
auto const zlibVersion = loader.load<char const* (void)>("zlibVersion");
std::cout << "zlib version: " << zlibVersion() << std::endl;
return 0;
}