distinguishing between static and non-static methods in c++ at compile time? - c++

For some tracing automation for identifying instances i want to call either:
a non-static method of the containing object returning its identifier
something else which always returns the same id
My current solution is to have a base class with a method which() and a global function which() which should be used if not in the context of an object.
This however does not work for static member functions, here the compiler prefers the non-static method over the global one.
Simplified example:
class IdentBase
{
public:
Ident(const std::string& id) _id(id) {}
const std::string& which() const { return _id; }
private:
const std::string _id;
};
const std::string& which() { static const std::string s("bar"); return s; }
#define ident() std::cout << which() << std::endl
class Identifiable : public IdentBase
{
public:
Identifiable() : Ident("foo") {}
void works() { ident(); }
static void doesnt_work() { ident(); } // problem here
};
Can i somehow avoid using work-arounds like a special macro for static member functions (maybe using some template magic)?

Define a function template that returns a default identifier for all types.
template<typename T>
const std::string& which(const T& object)
{ static const std::string s("bar"); return s; }
Specialize the function template for the specific class.
class IdentBase
{
public:
IdentBase(const std::string& id): _id(id) {}
const std::string& id() const { return _id; }
private:
const std::string _id;
};
template<>
const std::string& which(const IdentBase& object)
{ return object.id(); }
Call the function template by passing an instance that you want to identify.
int main()
{
int i;
std::cout << which(i) << std::endl;
IdentBase foo("foo");
std::cout << which(foo) << std::endl;
return 0;
}

You might be able to to use is_member_function_pointer from the Boost TypeTraits library. sbi's suggestion of using different code in the static and non-static cases is probably better though.

Do you need a different identifier for every instance of each class as in your example, or are you just trying to identify which class is in the trace?
Changing your which() function and _id member to static would expose them both to your static member functions, and as a bonus decrease your memory usage.

Related

Dynamic member pointer array

Is it possible to create a dynamic array to save the names of each variable in a structure?
typedef struct dataSave {
uint8_t nb;
bool state;
uint16_t dataIRArray[512];
} dataSave_t;
dataSave_t mysave;
template <typename T>
struct config_t {
auto T::*var;
char* name;
};
const config_t<dataSave_t> config[] = {
{&dataSave_t::nb, "nb"},
{&dataSave_t::state, "state"},
{&dataSave_t::dataIRArray, "dataIRArray"}
};
The types of the structure's variables are different, and always generate an error:
error: non-static data member declared with placeholder 'auto'
I need to create something similar to dynamically going through a JSON and converting the JSON data just by adding it to the config list.
I guess you want something like this:
template <typename owner>
struct desc_base
{
virtual ~desc_base() = default;
virtual std::string to_string(const owner&) = 0;
virtual void from_string(owner&, std::string_view) = 0;
const std::string name;
desc_base(std::string_view name) : name(name) {}
};
template <typename owner, typename member>
struct desc : desc_base<owner>
{
member owner::*ptr;
std::string to_string(const owner& o) override { return my_to_string(o.*ptr); }
void from_string(owner& o, std::string_view s) override { my_from_string(s, o.*ptr); }
desc (member owner::*ptr, std::string_view name) : desc_base<owner>(name), ptr(ptr) {}
};
template <typename owner, typename member>
std::unique_ptr<desc<owner, member>>
make_desc(member owner::*ptr, std::string_view name) { return std::make_unique<desc<owner, member>>(ptr, name); }
const std::unique_ptr<desc_base<dataSave_t>> config[] {
make_desc(&dataSave_t::nb, "nb"),
make_desc(&dataSave_t::state, "state"),
make_desc(&dataSave_t::dataIRArray, "dataIRAArray")
};
This uses basic polymorphism technique to store an array of (smart pointers to) base class objects, where all the real work being done by the derived objects via virtual functions. Real work in this case being from_string and to_string. You can replace them with functions doing whatever real work you need to do, or just define my_to_string and my_from_string.

C++ automatically choose correct overloaded function based on argument type

I'm creating a interface OutputItem<T> for writing to a json object. I want there to be different modes of writing to the json object, thus I have provided a overloaded method json_serialize which takes a SetConstructType* or AppendConstructType* argument, which are derived structs of ConstructType. Upon construction of OutputItem<T>, I want the user to pass a ConstructType* in the constructor of OutputItem<T> which will be saved to const ConstructType* constructType to be used later to automatically pick the right overloaded type when the public method void write(nlohmann::json& json) is called.
However I'm getting a error:
'void OutputItem::json_serialize(const SetConstructType *,nlohmann::json &)': cannot convert argument 1 from 'const ConstructType *' to 'const SetConstructType *'
Can someone show me the correct way of achieving this automatic overload resolution? Additionally is this a example of a SFINAE design?
Thanks
struct ConstructType {
protected:
ConstructType() {}
};
struct SetConstructType : public ConstructType {};
struct AppendConstructType : public ConstructType {};
static SetConstructType* SetConstruct;
static AppendConstructType* AppendConstruct;
template<typename T>
struct OutputItem {
OutputItem(const std::string& cgroupName, const std::string& citemName, const T& cdata, ConstructType* cconstructType)
: itemName(citemName), groupName(cgroupName), data(cdata), constructType(cconstructType) {}
const std::string itemName;
const std::string groupName;
const T data;
const ConstructType* constructType;
void write(nlohmann::json& json) {
json_serialize(constructType, json);
}
private:
void json_serialize(const SetConstructType*, nlohmann::json& json) {
json[groupName][itemName] = data;
}
void json_serialize(const AppendConstructType*, nlohmann::json& json) {
json[groupName][itemName].push_back(data);
}
};
Usage
json response;
OutputItem<int> item1("testgroup", "item1", 2, AppendConstruct);
OutputItem<int> item2("testgroup", "item2", 2, SetConstruct);
item1.write(response);
item2.write(response);
Since you can't select an overload at runtime, you need a more dynamic mechanism.
It is difficult to solve this with your external hierarchy since you can't have virtual templates.
One alternative would be to redirect through a member function pointer instead.
Illustration (without all your parameters and data):
enum class Construction
{
Set,
Append
};
template<typename T>
class OutputItem {
public:
OutputItem(Construction kind): construct(select(kind)) {}
void write() { (this->*construct)(); }
private:
using ConstructType = void (OutputItem::*)();
ConstructType construct;
ConstructType select(Construction c)
{
static ConstructType cs[] = { &OutputItem::setConstruct,
&OutputItem::appendConstruct };
return cs[static_cast<int>(c)];
}
void setConstruct() { std::cout << "Set\n"; }
void appendConstruct() { std::cout << "Append\n"; }
};
//...
int main()
{
OutputItem<int> o0(Construction::Set);
o0.write();
OutputItem<std::string> o1(Construction::Append);
o1.write();
}

unique container for template class

I have an algorithm (not preseted here) which takes as input different parameters (int, float, vectors).
My idea of design was to have an container which holds all these differents parameters.
To achive this, I have a base class Parameter and a derivated template class TypeParameter.
These parameters will be holded in a container.
The design is presented below:
#pragma once
#include <utility>
#include <memory>
#include <string>
#include <vector>
namespace parameter
{
/*
Interface for parameter
*/
class Parameter
{
public:
Parameter() {}
Parameter(std::string param_name) : name(param_name) {}
Parameter(const Parameter&& other) noexcept : name(std::move(other.name)) {}
virtual ~Parameter() {}
inline const std::string get_name() { return name; }
private:
std::string name;
};
/*
*/
template<class T>
class TypeParameter
: public Parameter
{
public:
TypeParameter(std::string param_name, T new_value) : Parameter(param_name), value(new_value) {}
TypeParameter(const TypeParameter&& other) noexcept : Parameter(std::move(other)), value(std::move(other.T)) {}
inline const T get_value() { return value; }
private:
T value;
};
/*
Container for parameters
*/
class ParameterSet
{
public:
ParameterSet() {}
void add(std::unique_ptr<Parameter> param) { data.push_back(std::move(param)); }
private:
std::vector <std::unique_ptr<Parameter>> data;
};
} //namespace parameter
The main is:
#include <iostream>
#include <string>
#include "Parameter.h"
using parameter::TypeParameter;
using parameter::Parameter;
using parameter::ParameterSet;
void foo(std::unique_ptr<Parameter> p)
{
std::cout << p->get_value(); // ERROR
}
int main(int argc, char *argv[])
{
TypeParameter<int> *iparam = new TypeParameter<int>("ee", 3);
std::unique_ptr<Parameter> p = std::make_unique <TypeParameter<int>>("foo", 3);
foo(std::move(p));
ParameterSet param_set;
param_set.add(std::unique_ptr<Parameter>(iparam));
param_set.add(std::move(p));
getchar();
}
My problem is I cannot get the value without a cast.
Hence, my question is how do I cast the unique_ptr from a Parameter class to derived TypeParameter.
Is there another way to design the container?
Thanks a lot!
You don't have to reinvent the wheel. There are a couple of classes you can use from the standard library:
std::variant.
As suggested by the comments, variant is a type-safe union of a pre-defined set of data types, which you put in the templates argument of variant.
For example, a std::variant<int,float,double> can hold any value of type int, float, or double, but nothing else.
To use the stored value, you can either use the visitor pattern with the std::visit() function. Other functions allow you to know which of the preset types is stored in the variable (index()) and to extract the value from it (using get()). If you try to extract the value of the wrong type, the get() function throws an exception
std::any
is another utility that can hold different data types. As opposed to variant, you don't have to know the types at compile-time. Basically, it stores a void* to the data with a typeinfo to remember its original type. You can then use any_cast to cast the variable back to its original type. Just like variant, an exception is thrown when trying to cast to the wrong type.
These two classes are available in C++ 17. If these features are not available to you, they were also included in boost (respectively boost:variant and boost:any)
You can store the set of values in a standard library container, e.g. in a std::vector<std::variant<int,float,double>> or a std::vector<std::any>>.
Alternative to std::variant/std::any is the old way polymorphism:
class Parameter
{
public:
Parameter(const std::string& param_name) : name(param_name) {}
virtual ~Parameter() = default;
const std::string& get_name() const { return name; }
virtual void printValue() const = 0;
// Other virtual methods
private:
std::string name;
};
template<class T>
class TypeParameter : public Parameter
{
public:
TypeParameter(const std::string& name, const T& t) : Parameter(name), value(t) {}
// Non virtual method when we don't access it by base class.
const T& get_value() const { return value; }
void printValue() const { std::cout << value; }
private:
T value;
};
And then your
void foo(const Parameter& p)
{
std::cout << p.get_value(); // ERROR
}
becomes
void foo(const Parameter& p)
{
p.print();
}
If you don't want to add many virtual methods to Parameter, then Visitor pattern can help, but then you have to know each derived types.

OneOfAType container -- storing one each of a given type in a container -- am I off base here?

I've got an interesting problem that's cropped up in a sort of pass based compiler of mine. Each pass knows nothing of other passes, and a common object is passed down the chain as it goes, following the chain of command pattern.
The object that is being passed along is a reference to a file.
Now, during one of the stages, one might wish to associate a large chunk of data, such as that file's SHA512 hash, which requires a reasonable amount of time to compute. However, since that chunk of data is only used in that specific case, I don't want all file references to need to reserve space for that SHA512. However, I also don't want other passes to have to recalculate the SHA512 hash over and over again. For example, someone might only accept files which match a given list of SHA512s, but they don't want that value printed when the file reference gets to the end of the chain, or perhaps they want both, or... .etc.
What I need is some sort of container which contain only one of a given type. If the container does not contain that type, it needs to create an instance of that type and store it somehow. It's basically a dictionary with the type being the thing used to look things up.
Here's what I've gotten so far, the relevant bit being the FileData::Get<t> method:
class FileData;
// Cache entry interface
struct FileDataCacheEntry
{
virtual void Initalize(FileData&)
{
}
virtual ~FileDataCacheEntry()
{
}
};
// Cache itself
class FileData
{
struct Entry
{
std::size_t identifier;
FileDataCacheEntry * data;
Entry(FileDataCacheEntry *dataToStore, std::size_t id)
: data(dataToStore), identifier(id)
{
}
std::size_t GetIdentifier() const
{
return identifier;
}
void DeleteData()
{
delete data;
}
};
WindowsApi::ReferenceCounter refCount;
std::wstring fileName_;
std::vector<Entry> cache;
public:
FileData(const std::wstring& fileName) : fileName_(fileName)
{
}
~FileData()
{
if (refCount.IsLastObject())
for_each(cache.begin(), cache.end(), std::mem_fun_ref(&Entry::DeleteData));
}
const std::wstring& GetFileName() const
{
return fileName_;
}
//RELEVANT METHOD HERE
template<typename T>
T& Get()
{
std::vector<Entry>::iterator foundItem =
std::find_if(cache.begin(), cache.end(), boost::bind(
std::equal_to<std::size_t>(), boost::bind(&Entry::GetIdentifier, _1), T::TypeId));
if (foundItem == cache.end())
{
std::auto_ptr<T> newCacheEntry(new T);
Entry toInsert(newCacheEntry.get(), T::TypeId);
cache.push_back(toInsert);
newCacheEntry.release();
T& result = *static_cast<T*>(cache.back().data);
result.Initalize(*this);
return result;
}
else
{
return *static_cast<T*>(foundItem->data);
}
}
};
// Example item you'd put in cache
class FileBasicData : public FileDataCacheEntry
{
DWORD dwFileAttributes;
FILETIME ftCreationTime;
FILETIME ftLastAccessTime;
FILETIME ftLastWriteTime;
unsigned __int64 size;
public:
enum
{
TypeId = 42
}
virtual void Initialize(FileData& input)
{
// Get file attributes and friends...
}
DWORD GetAttributes() const;
bool IsArchive() const;
bool IsCompressed() const;
bool IsDevice() const;
// More methods here
};
int main()
{
// Example use
FileData fd;
FileBasicData& data = fd.Get<FileBasicData>();
// etc
}
For some reason though, this design feels wrong to me, namely because it's doing a whole bunch of things with untyped pointers. Am I severely off base here? Are there preexisting libraries (boost or otherwise) which would make this clearer/easier to understand?
As ergosys said already, std::map is the obvious solution to your problem. But I can see you concerns with RTTI (and the associated bloat). As a matter of fact, an "any" value container does not need RTTI to work. It is sufficient to provide a mapping between a type and an unique identifier. Here is a simple class that provides this mapping:
#include <stdexcept>
#include <boost/shared_ptr.hpp>
class typeinfo
{
private:
typeinfo(const typeinfo&);
void operator = (const typeinfo&);
protected:
typeinfo(){}
public:
bool operator != (const typeinfo &o) const { return this != &o; }
bool operator == (const typeinfo &o) const { return this == &o; }
template<class T>
static const typeinfo & get()
{
static struct _ti : public typeinfo {} _inst;
return _inst;
}
};
typeinfo::get<T>() returns a reference to a simple, stateless singleton which allows comparisions.
This singleton is created only for types T where typeinfo::get< T >() is issued anywhere in the program.
Now we are using this to implement a top type we call value. value is a holder for a value_box which actually contains the data:
class value_box
{
public:
// returns the typeinfo of the most derived object
virtual const typeinfo& type() const =0;
virtual ~value_box(){}
};
template<class T>
class value_box_impl : public value_box
{
private:
friend class value;
T m_val;
value_box_impl(const T &t) : m_val(t) {}
virtual const typeinfo& type() const
{
return typeinfo::get< T >();
}
};
// specialization for void.
template<>
class value_box_impl<void> : public value_box
{
private:
friend class value_box;
virtual const typeinfo& type() const
{
return typeinfo::get< void >();
}
// This is an optimization to avoid heap pressure for the
// allocation of stateless value_box_impl<void> instances:
void* operator new(size_t)
{
static value_box_impl<void> inst;
return &inst;
}
void operator delete(void* d)
{
}
};
Here's the bad_value_cast exception:
class bad_value_cast : public std::runtime_error
{
public:
bad_value_cast(const char *w="") : std::runtime_error(w) {}
};
And here's value:
class value
{
private:
boost::shared_ptr<value_box> m_value_box;
public:
// a default value contains 'void'
value() : m_value_box( new value_box_impl<void>() ) {}
// embedd an object of type T.
template<class T>
value(const T &t) : m_value_box( new value_box_impl<T>(t) ) {}
// get the typeinfo of the embedded object
const typeinfo & type() const { return m_value_box->type(); }
// convenience type to simplify overloading on return values
template<class T> struct arg{};
template<class T>
T convert(arg<T>) const
{
if (type() != typeinfo::get<T>())
throw bad_value_cast();
// this is safe now
value_box_impl<T> *impl=
static_cast<value_box_impl<T>*>(m_value_box.get());
return impl->m_val;
}
void convert(arg<void>) const
{
if (type() != typeinfo::get<void>())
throw bad_value_cast();
}
};
The convenient casting syntax:
template<class T>
T value_cast(const value &v)
{
return v.convert(value::arg<T>());
}
And that's it. Here is how it looks like:
#include <string>
#include <map>
#include <iostream>
int main()
{
std::map<std::string,value> v;
v["zero"]=0;
v["pi"]=3.14159;
v["password"]=std::string("swordfish");
std::cout << value_cast<int>(v["zero"]) << std::endl;
std::cout << value_cast<double>(v["pi"]) << std::endl;
std::cout << value_cast<std::string>(v["password"]) << std::endl;
}
The nice thing about having you own implementation of any is, that you can very easily tailor it to the features you actually need, which is quite tedious with boost::any. For example, there are few requirements on the types that value can store: they need to be copy-constructible and have a public destructor. What if all types you use have an operator<<(ostream&,T) and you want a way to print your dictionaries? Just add a to_stream method to box and overload operator<< for value and you can write:
std::cout << v["zero"] << std::endl;
std::cout << v["pi"] << std::endl;
std::cout << v["password"] << std::endl;
Here's a pastebin with the above, should compile out of the box with g++/boost: http://pastebin.com/v0nJwVLW
EDIT: Added an optimization to avoid the allocation of box_impl< void > from the heap:
http://pastebin.com/pqA5JXhA
You can create a hash or map of string to boost::any. The string key can be extracted from any::type().

Map of boost function of different types?

i was wondering if there was a way to do this in C++?
void func1(const std::string& s)
{
std::cout << s << std::endl;
}
void func2(int me)
{
std::cout << me << std::endl;
}
int main()
{
std::map<std::string, boost::function< ??? > > a_map;
a_map["func1"] = &func1;
a_map["func1"]("HELLO");
}
Is there any way to do what i have above using boost function and a map?
There are ways to store the functions, the problem is, in order to be able to call the function with the desired argument you'd have to know the calling signature of the function anyways, and if you have that information, you might as well use separate maps, or use a more complicated object than boost::function.
If you're willing to do a bit of work and have a finite number of signatures, you could just do something like this:
class MultiFunc
{
protected:
MultiFunc() {}
public:
typedef void (*stringFunc)(const std::string&);
typedef void (*intFunc)(int);
static MultiFunc *Create(stringFunc function);
static MultiFunc *Create(intFunc function);
virtual void operator()(const string &) { throw exception(); }
virtual void operator()(int) { throw exception(); }
virtual ~MultiFunc();
};
class MultiFuncString : public MultiFunc
{
private:
stringFunc Function;
public:
MultiFuncString(stringFunc function) : Function(function) {}
virtual void operator()(const string &arg) { Function(arg); }
};
class MultiFuncInt : public MultiFunc
{
private:
intFunc Function;
public:
MultiFuncInt(intFunc function) : Function(function) {}
virtual void operator()(int arg) { Function(arg); }
};
MultiFunc *MultiFunc::Create(MultiFunc::stringFunc function)
{
return new MultiFuncString(function);
}
MultiFunc *MultiFunc::Create(MultiFunc::intFunc function)
{
return new MultiFuncInt(function);
}
void func1(const std::string& s)
{
std::cout << s << std::endl;
}
void func2(int me)
{
std::cout << me << std::endl;
}
int main()
{
map<string, MultiFunc *> a_map;
a_map["func1"] = MultiFunc::Create(&func1);
(*a_map["func1"])("Hello");
a_map["func2"] = MultiFunc::Create(&func2);
(*a_map["func2"])(3);
// Remember to delete the MultiFunc object, or use smart pointers.
}
This outputs:
Hello
3
Unfortunately, you can't make templated virtual functions or you easily generalize this all.
You probably can't use the std::map since it is a homogenous container. Try, something like boost::variant (they support the visitor pattern) or boost::tuple
What you are trying to do sounds a little weird. Normally, you would have a container be a collection of abstract types or objects or functions with the same signature. Otherwise, how would you know how to call the function when you are iterating the container? I like to make the container a collection of function objects with a known signature, then use Boost.Bind to store closures that call the function with additional arguments.
For example:
typedef boost::function<void, void> Function;
typedef std::map<std::string, Function> Functions;
Functions functions:
void foo()
{
...
}
functions["foo"] = foo;
void bar(std::string &s)
{
...
}
// binds the value "hello" to the s parameter
functions["bar"] = boost::bind(bar, "hello");
read this link below. It talks about using boost::bind to store the function pointers in std::map
http://www.gamedev.net/community/forums/topic.asp?topic_id=526381&whichpage=1&#3411515
store interfaces:
struct IStringData
{
virtual std::string get() const = 0;
virtual ~IStringData() {}
};
and make implementaions, one will just hold string value, other implementation will store functor, maybe you will have other implementations in future.
No. You can't. Since boost::function isn't polymorphic, it breaks down there. (It takes a fixed set of argument types.)
There was talk about work in that direction on the boost mail-list, though, so search the archives and see if there is some code you could youse.
A workaround would be to use boost::function but then you need to add to the map not your real functions (i.e. func1/func2) but dispatch functions that extracts the type from the any-container and calls the real function. (And bails if it's wrong, just as in any dynamic langugage.)