I want to create a macro for a template function
something on the lines of
#define CHECK_MIN(T)(value, target) checkmin(T value, T target) \
checkmin<T>(T val, T target, __FUNCTION__, __LINE__)
template<typename T> checkmin(T val, T target, const char* functionName, long lineNumber)
{
// Check if the val is less than target
// Construct a std::string using the function name and line name
// throw std:: exception passing the string constructed above.
}
I am not able to get the syntax to achieve this. Any ideas?
You can do it by following way:
#include <iostream>
using namespace std;
template<typename T>
void checkmin(T val, T target, const char* functionName, long lineNumber)
{
// Check if the val is less than target
// Construct a std::string using the function name and line name
// throw std:: exception passing the string constructed above.
}
#define CHECK_MIN(value, target) \
checkmin(value,target, __FUNCTION__, __LINE__);
int main() {
/*Not using new in object definitions so I don't have to delete them afterwards since pointers don't stay in memory*/
CHECK_MIN(5,6);
return 0;
}
Related
My goal is to iterate over all functions of the namespace until a function returns me a valid strategy(enum). Each function can take different arguements.
enum class strategyType
{
Strategy1,
Strategy2,
Strategy3,
Strategy4,
Strategy5,
InvalidStrategy
}
namespace allFunctionStrategy
{
strategyType algorithmMl(int v1,int v2);
strategyType algorithmHeuristic(int v3,string s1);
strategyType algorithmHeuristic(string s1,string s2);
... n such function's
}
class strategyContext
{
int v1,v2,v3;
string s1,s2;
/*i want to add iterator logic here*/
}
Write a function that calls them:
void strategyContext::execute() {
if (algorithmM1(v1, v2) != strategyType::InvalidStrategy)
;
else if (algorithmHeuristic(v3, s1) != strategyType::InvalidStrategy)
;
else if (algorithmHeuristic(s1, s2) != strategyType::InvalidStrategy)
;
else
throw no_valid_strategy();
}
or, if the word "looping" was meant as a requirement, write wrappers and put the function pointers into an array:
strategyType strategyContext::wrap_algorithmM1() {
return algorithmM1(v3, s1);
}
strategyType strategyContext::wrap_algorithmHeuristic1() {
return algorithmHeuristic(v3, s1);
}
strategyType strategyContext::wrap_algorithmHeuristic2() {
return algorithmHeuristic(s1, s2);
}
typedef strategyType (strategyContext::*fptr)();
fptr pointers[] = {
&strategyContext::wrap_algorithmM1,
&strategyContext::wrap_algorithmHeuristic1,
&strategyContext::wrap_algorithmHeuristic2
};
void strategyContext::execute() {
for (auto iter = std::begin(pointers);
iter != std::end(pointers);
++iter) {
if ((this->*(*iter))() != strategyType::InvalidStrategy)
return;
}
throw no_valid_strategy();
}
Okay, first things first, you probably don't need to iterate over every function in the namespace. I'm going to show you how to use two macros to implement basic reflection, but you should probably also rethink what you're trying to do. Also, this is going to be really messy code.
First, we want every function to take the same parameters and return the same thing. For your use case, you can add all the parameters that the functions could use to a struct.
struct PossibleParams
{
//You can expand this if you want
int x, y, z;
};
struct Output {};
Next, we need a place to store the functions. Import functional and unordered_map and add the following macro.
#define ReflectableNamespace(name) namespace __REFLECTABLE__\
{ struct __NAMESPACE_ ## name ## __ { inline static std::unordered_map<std::string, std::function<Output(PossibleParams)>> funcs; }; \
struct __ ## name ## _MAP_ADDER__ \
{\
__ ## name ## _MAP_ADDER__ (const std::string& Name, std::function<Output(PossibleParams)> func) { __NAMESPACE_ ## name ## __::funcs[Name] = func; }\
};\
}\
namespace name
Here's what that macro does:
Defines an unordered_map that maps between the function name and the function in the __REFLECTABLE__ namespace.
Defines a struct that will let us add the function to this map at startup through its constructor
Begins the namespace that you're trying to make
This second macro will declare a function that can be iterated over and add it to the functions map.
#define ReflectableFunction(namespace, name) Output name (PossibleParams);\
struct __NAMESPACE_ ## namespace ## _ ## name ## _adder__ {\
inline static const __REFLECTABLE__::__ ## namespace ## _MAP_ADDER__ Adder = __REFLECTABLE__::__ ## namespace ## _MAP_ADDER__ (#name, name);\
}
This second struct declares a function that returns an Output and takes a PossibleParams as a parameter. It then creates an instance of that namespace's map adder object so that the function will be added to the namespace's map on startup. Since everything is inline, this should be able to be used in header files.
To call one of these functions, just use __REFLECTABLE__::__NAMESPACE_YourNamespace__::funcs["TheFunction"]({...});
Full working example:
struct PossibleParams
{
//Can expand this if you want
int x, y, z;
};
struct Output {};
#include <unordered_map>
#include <functional>
#define ReflectableNamespace(name) namespace __REFLECTABLE__\
{ struct __NAMESPACE_ ## name ## __ { inline static std::unordered_map<std::string, std::function<Output(PossibleParams)>> funcs; }; \
struct __ ## name ## _MAP_ADDER__ \
{\
__ ## name ## _MAP_ADDER__ (const std::string& Name, std::function<Output(PossibleParams)> func) { __NAMESPACE_ ## name ## __::funcs[Name] = func; }\
};\
}\
namespace name
#define ReflectableFunction(namespace, name) Output name (PossibleParams);\
struct __NAMESPACE_ ## namespace ## _ ## name ## _adder__ {\
inline static const __REFLECTABLE__::__ ## namespace ## _MAP_ADDER__ Adder = __REFLECTABLE__::__ ## namespace ## _MAP_ADDER__ (#name, name);\
}
#include <iostream>
ReflectableNamespace(MyNamespace)
{
ReflectableFunction(MyNamespace, func);
Output func(PossibleParams)
{
std::cout << "Hello" << std::endl;
return {};
}
}
int main()
{
std::cout << __REFLECTABLE__::__NAMESPACE_MyNamespace__::funcs.size() << std::endl;
__REFLECTABLE__::__NAMESPACE_MyNamespace__::funcs["func"]({});
return 0;
}
One last thing. If you're planning to iterate through this map a lot, it may be better to replace it with a normal map since it may be faster to iterate through. Or, if you don't care about the function's name, you could consider replacing the map with a vector. I hope this helps!
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.
I need to do the following:
const char* my_var = "Something";
REGISTER(my_var);
const char* my_var2 = "Selse";
REGISTER(my_var2);
...
concst char* all[] = { OUTPUT_REGISTERED }; // inserts: "my_var1, my_var2, ..."
REGISTER and OUTPUT_REGISTERED are preprocesor macros. This would be great for large number of strings, like ~100. Is it possible to accomplish this?
PS. The code belongs to level-0 "block" – i.e. it is not inside any function. AFAIK, I cannot call regular functions there.
#include <iostream>
#include <vector>
using namespace std;
vector<const char*>& all()
{
static vector<const char*> v;
return v;
}
struct string_register
{
string_register(const char* s)
{
all().push_back(s);
}
};
#define REGISTER3(x,y,sr) string_register sr ## y(x)
#define REGISTER2(x,y) REGISTER3(x,y,sr)
#define REGISTER(x) REGISTER2(x, __COUNTER__)
REGISTER("foo");
REGISTER("bar");
int main()
{
}
include/TestBullet.h:12: error: expected constructor, destructor, or type conver
sion before '(' token
I hate C++ error messages... lol ^^
Basically, I'm following what was written in this post to try to create a factory class for bullets so they can be instantiated from a string, which will be parsed from an xml file, because I don't want to have a function with a switch for all of the classes because that looks ugly.
Here is my TestBullet.h:
#pragma once
#include "Bullet.h"
#include "BulletFactory.h"
class TestBullet : public Bullet {
public:
void init(BulletData& bulletData);
void update();
};
REGISTER_BULLET(TestBullet); <-- line 12
And my BulletFactory.h:
#pragma once
#include <string>
#include <map>
#include "Bullet.h"
#define REGISTER_BULLET(NAME) BulletFactory::reg<NAME>(#NAME)
#define REGISTER_BULLET_ALT(NAME, CLASS) BulletFactory::reg<CLASS>(NAME)
template<typename T> Bullet * create() { return new T; }
struct BulletFactory {
typedef std::map<std::string, Bullet*(*)()> bulletMapType;
static bulletMapType map;
static Bullet * createInstance(char* s) {
std::string str(s);
bulletMapType::iterator it = map.find(str);
if(it == map.end())
return 0;
return it->second();
}
template<typename T>
static void reg(std::string& s) {
map.insert(std::make_pair(s, &create<T>));
}
};
Thanks in advance.
And unrelated to the error, but is there a way to let Bullet include BulletFactory without creating tons of errors (because of circular inclusion)? This way I would be able to remove #include "BulletFactory.h" from the top of all of the bullet subclasses.
I don't think you can call functions outside of functions (as long as you don't use the result to initialize a global).
Here's how you get what you want. (Not using your code, exactly, skips including headers, etc. Just for the idea.):
// bullet_registry.hpp
class bullet;
struct bullet_registry
{
typedef bullet* (*bullet_factory)(void);
std::map<std::string, bullet_factory> mFactories;
};
bullet_registry& get_global_registry(void);
template <typename T>
struct register_bullet
{
register_bullet(const std::string& pName)
{
get_global_registry().mFactories.insert(std::make_pair(pName, create));
}
static bullet* create(void)
{
return new T();
}
};
#define REGISTER_BULLET(x) \
namespace \
{ \
register_bullet _bullet_register_##x(#x); \
}
// bullet_registry.cpp
bullet_registry& get_global_registry(void)
{
// as long as this function is used to get
// a global instance of the registry, it's
// safe to use during static initialization
static bullet_registry result;
return result; // simple global variable with lazy initialization
}
// bullet.hpp
struct my_bullet : bullet { };
// bullet.cpp
REGISTER_BULLET(my_bullet)
This works by making a global variable, which will be initialized at some point during static initialization. When that happens, in its constructor it accesses the global registry and registers it with the name, and the function used to create bullets.
Since static initialization order is unspecified, we put the global manager in a function, so when that function is called the first time the manager is created on-demand and used. This prevents us from using an uninitialized manager, which could be the case if it were a simple global object.
Free free to ask for clarifications.
reg() is a function. You can't call a function without a scope.
Out of curiosity, I thought I'd try and write a basic C++ class that mimics C#'s multiple delegate pattern. The code below mostly does the job, with the nasty sacrifice of losing almost all type-safety, but having to use the initial dummy parameter to set up the va_list really seems a bit off. Is there a way to use va_list without this?
I do realize there are ways to do this with (for example) boost, but I was aiming for something dead simple that used just the standard library.
#include <vector>
#include <iostream>
#include <string>
#include <stdarg.h>
#include <algorithm>
using namespace std;
class CDelegate
{
public:
virtual bool operator()(va_list params) = 0;
};
class CMultipleDelegateCaller
{
public:
typedef vector<CDelegate*> CDelegateVector;
CMultipleDelegateCaller& operator+=(CDelegate &rDelegate)
{
m_apDelegates.push_back(&rDelegate);
return (*this);
}
CMultipleDelegateCaller& operator-=(CDelegate &rDelegate)
{
CDelegateVector::iterator iter =
find(m_apDelegates.begin(), m_apDelegates.end(), &rDelegate);
if (m_apDelegates.end() != iter) m_apDelegates.erase(iter);
return (*this);
}
bool Call(int iDummy, ...)
{
va_list params;
CDelegate* pDelegate;
CDelegateVector::iterator iter;
for (iter = m_apDelegates.begin(); iter != m_apDelegates.end(); ++iter)
{
pDelegate = *iter;
va_start(params, iDummy);
if (!(*pDelegate)(params)) return false;
va_end(params);
}
return true;
}
private:
CDelegateVector m_apDelegates;
};
class CTestDelegate:
public CDelegate
{
public:
CTestDelegate():m_iId(++s_iCount) {}
virtual bool operator()(va_list params)
{
int iIntParam = va_arg(params, int);
char* szCharPtrParam = va_arg(params, char*);
string* psStringParam = va_arg(params, string*);
cout<<m_iId<<"{"
<<iIntParam<<", "
<<szCharPtrParam<<", "
<<*psStringParam<<"}"<<endl;
return true;
}
int m_iId;
static int s_iCount;
};
int CTestDelegate::s_iCount = 0;
int main(int argc, char* argv[])
{
CMultipleDelegateCaller cDelegateCaller;
CTestDelegate cTestDelegate1;
CTestDelegate cTestDelegate2;
cout<<"--------------------"<<endl;
cDelegateCaller += cTestDelegate1;
cDelegateCaller += cTestDelegate2;
string sString("World");
cDelegateCaller.Call(1, 2, "Hello", &sString);
cout<<"--------------------"<<endl;
cDelegateCaller -= cTestDelegate1;
cDelegateCaller.Call(1, 2, "Hello", &sString);
cout<<"--------------------"<<endl;
cDelegateCaller -= cTestDelegate2;
cDelegateCaller.Call(1, 2, "Hello", &sString);
cout<<"--------------------"<<endl;
cin>>sString;
return 0;
}
Functions with ellipsis in C++ is only for compatibility with C. Using C++ I'd return temporary helper object in Call function and add template operator% to pass variable number of arguments. To use it in the following way:
cDelegateCaller.Call() % 2 % "Hello" % sString; // dummy argument isn't required
As to your question, Standard requires to invoke va_start before any access to the unnamed arguments. And va_start requires second argument which is the identifier of the rightmost parameter in the variable parameter list in the function definition.
Out of Kirill's answer you can conclude that it's possible to create a type-safe delegate, using a template argument-combining function. This function also needs a dummy starting point, but has the benefit of type-safety.
The FastFormat library uses this, boost uses this, and I once provided another example in an answer to another question.