I would like to have a struct (or something similar) in C++, that will allow access to its members dynamically. It should have a generic getter and setters that receive the member name as a string, and return some sort of variant type (e.g. boost::variant).
I was thinking it could be implemented using boost::fusion::map, by adding a string representing the name of each member, and building an STL map between strings and getter or setter functions. I don't want to reinvent the wheel, so I was hoping something similar already existed.
What do you think? Would my idea work? Do you know other ways to accomplish my goal?
fusion is an approach, but why not store your "fields" in a std::map keyed by a std::string, where the payload is the boost::variant...
i.e.
struct generic
{
std::map<std::string, boost::variant<foo, bar, bob, int, double> > _impl;
};
and then you can just lookup the key in your getter/setter...
heck, wrap the variant in an optional and you could have optional fields!
a more complex example:
class foo
{
public:
typedef boost::variant<int, double, float, string> f_t;
typedef boost::optional<f_t&> return_value;
typedef map<string, return_value> ref_map_t;
foo() : f1(int()), f2(double()), f3(float()), f4(string()), f5(int())
{
// save the references..
_refs["f1"] = return_value(f1);
_refs["f2"] = return_value(f2);
_refs["f3"] = return_value(f3);
_refs["f4"] = return_value(f4);
_refs["f5"] = return_value(f5);
}
int getf1() const { return boost::get<int>(f1); }
double getf2() const { return boost::get<double>(f2); }
float getf3() const { return boost::get<float>(f3); }
string const& getf4() const { return boost::get<string>(f4); }
int getf5() const { return boost::get<int>(f5); }
// and setters..
void setf1(int v) { f1 = v; }
void setf2(double v) { f2 = v; }
void setf3(float v) { f3 = v; }
void setf4(std::string const& v) { f4 = v; }
void setf5(int v) { f5 = v; }
// key based
return_value get(string const& key)
{
ref_map_t::iterator it = _refs.find(key);
if (it != _refs.end())
return it->second;
return return_value();
}
template <typename VT>
void set(string const& key, VT const& v)
{
ref_map_t::iterator it = _refs.find(key);
if (it != _refs.end())
*(it->second) = v;
}
private:
f_t f1;
f_t f2;
f_t f3;
f_t f4;
f_t f5;
ref_map_t _refs;
};
int main(void)
{
foo fancy;
fancy.setf1(1);
cout << "f1: " << fancy.getf1() << endl;
fancy.set("f1", 10);
cout << "f1: " << fancy.getf1() << endl;
return 0;
}
You are asking for Reflection in C++ which I think is not available. You will have to come up with something of your own.
What I did for this was a boost::cons-like type-list that contains my members and some kind of description. I then build this mapping by successively adding my members to a "meta-info" data structure by "chained" function calls. The whole thing looks very similar to defining a class in boost.python. If you actually use boost::cons, it should also work as a sequence in boost.fusion, so you can iterate nicely over your data. Maybe you can use a boost.fusion map instead to get log(n) access times at run-time, but it seems their size is limited until variadic templates are available.
Related
Is it better to do:
class Foo{
std:string option1(MY_ENUM type){
static const std:string f1 = "a";
static const std:string f2 = "b";
static const std:string f3 = "c";
// ...
switch (type) {
case (TYPE_1):{
return f1;
break;
}
case (TYPE_2):{
return f2;
break;
}
// ...
}
}
Or do this:
class Foo {
private:
const std:string f1 = "a";
const std:string f2 = "b";
const std:string f3 = "c";
public:
std:string option1(MY_ENUM type){
// ...
switch (type){
case (TYPE_1):{
return f1;
break;
}
case (TYPE_2):{
return f2;
break;
}
// ...
}
}
Likewise I would do something similar to convert the enum to the string.
Is it better to keep the strings as static const within the function, or as private within the class ?
- No one else is going to edit the class but me.
- It doesn't really matter if any other functions inside the class know what the values of the strings are, and since it is const they can't modify it anyway.
Which is cheaper and has less overhead at runtime and during compilation ? Which is a better practice ?
Cheaper would be not to use std::string at all since it will likely require run-time initialization and also use a lookup table to translate from enum to string:
const char *enumToStr(MY_ENUM type) {
static const char *const names[] = { "a", "b", "c" };
if (type < sizeof(names) / sizeof(names[0]))
return names[type];
return nullptr;
}
Unfortunately you can't use this kind of trick for a reverse conversion. Also this assumes that your enumerators have contiguous numerical values and you should be careful when adding or reordering your enum's values.
As for "where to put these values" question, it doesn't really matter from the "overhead" point of view as long as this array is static or global. I would suggest putting it into a global variable within an anonymous namespace inside the *.cpp file that defines these conversion functions, so that it can be used for both functions but isn't visible outside of this translation unit:
namespace {
const char *const names[] = ...;
}
The most common implementation in c++ is to setup a map for this:
#include <iostream>
#include <unordered_map>
#include <string>
enum MY_ENUM {
TYPE_1
, TYPE_2 = 42 // Mind the gap please!
};
const char* const option1(MY_ENUM type) {
static std::unordered_map<MY_ENUM, const char* const> enum2StringMap =
{ { TYPE_1, "a" }
, { TYPE_2, "b" }
// ...
};
if(enum2StringMap.find(type) == enum2StringMap.end()) {
// throw exception or do whatever to indicate an error
return "Invalid enum value";
}
return enum2StringMap[type];
}
For the vice versa option you might need to take the burden to keep a second map, and synchronize it with the 1st one:
MY_ENUM option1(const std::string& s) {
static std::unordered_map<std::string, MY_ENUM> string2EnumgMap =
{ { "a" , TYPE_1 }
, { "b" , TYPE_2 }
// ...
};
if(string2EnumgMap.find(s) == string2EnumgMap.end()) {
// throw exception or do whatever to indicate an error
}
return string2EnumgMap[s];
}
Another option making the synchonization easier (but may have other drawbacks regarding performance) could be using a boost::bimap.
int main() {
std::cout << option1(TYPE_1) << std::endl;
std::cout << option1(TYPE_2) << std::endl;
std::cout << option1("a") << std::endl;
std::cout << option1("b") << std::endl;
}
Output:
a
b
0
42
Not as "cheap" as #r3musn0x proposed solution, but eliminates the concerns mentioned in #KonstantinL's comment.
There will be a little overhead when the maps are initialized at first access, but any foolowing up search might be optimized to be O(log n) vs. O(n) time complexity.
See a working online demo.
A variation on #KonstantinL's approach; I too think you would be best served by avoiding std::strings to the extent that you can. But I would also like to avoid maps...
class Foo {
public:
enum MY_ENUM {
TYPE_1,
TYPE_2
};
protected:
using pair_type = std::pair<MY_ENUM, const char*>;
// the following will work with C++17:
// See also: https://stackoverflow.com/q/6114067/1593077
// about initializing std::arrays without specifying the length.
static constexpr const auto names_and_codes = std::array {
pair_type { TYPE_1, "a" },
pair_type { TYPE_2, "b" },
};
public:
static const char* name_of(MY_ENUM t) noexcept
{
auto iter = std::find_if(names_and_codes.begin(), names_and_codes.end(),
[&t](const auto& pair) { return pair.first == t; }
);
if (iter != names.end()) { return iter->second; }
return nullptr; // Or handle the not-found case differently
}
static MY_ENUM code_for(const char* name) noexcept
{
auto iter = std::find_if(names_and_codes.begin(), names_and_codes.end(),
[&t](const auto& pair) { return std::strcmp(pair.second, name) == 0; }
);
if (iter != names.end()) { return iter->first; }
return MY_ENUM{-1}; // Or handle the not-found case differently
}
// more code for class Foo
}
This uses a static array instead of a map; linear search in contiguous memory is faster than binary search on trees on with heap-allocated nodes - for a limited number of values, which seems to be the case for you. Also - no use of the heap at all here.
Notes:
This fixed-size-array-backed "map" can be factored out and made generic, in a separate header. It comes in useful sometimes.
If your array is sorted, you can make one of the searches binary.
I have a function that takes a vector-like input. To simplify things, let's use this print_in_order function:
#include <iostream>
#include <vector>
template <typename vectorlike>
void print_in_order(std::vector<int> const & order,
vectorlike const & printme) {
for (int i : order)
std::cout << printme[i] << std::endl;
}
int main() {
std::vector<int> printme = {100, 200, 300};
std::vector<int> order = {2,0,1};
print_in_order(order, printme);
}
Now I have a vector<Elem> and want to print a single integer member, Elem.a, for each Elem in the vector. I could do this by creating a new vector<int> (copying a for all Elems) and pass this to the print function - however, I feel like there must be a way to pass a "virtual" vector that, when operator[] is used on it, returns this only the member a. Note that I don't want to change the print_in_order function to access the member, it should remain general.
Is this possible, maybe with a lambda expression?
Full code below.
#include <iostream>
#include <vector>
struct Elem {
int a,b;
Elem(int a, int b) : a(a),b(b) {}
};
template <typename vectorlike>
void print_in_order(std::vector<int> const & order,
vectorlike const & printme) {
for (int i : order)
std::cout << printme[i] << std::endl;
}
int main() {
std::vector<Elem> printme = {Elem(1,100), Elem(2,200), Elem(3,300)};
std::vector<int> order = {2,0,1};
// how to do this?
virtual_vector X(printme) // behaves like a std::vector<Elem.a>
print_in_order(order, X);
}
It's not really possible to directly do what you want. Instead you might want to take a hint from the standard algorithm library, for example std::for_each where you take an extra argument that is a function-like object that you call for each element. Then you could easily pass a lambda function that prints only the wanted element.
Perhaps something like
template<typename vectorlike, typename functionlike>
void print_in_order(std::vector<int> const & order,
vectorlike const & printme,
functionlike func) {
for (int i : order)
func(printme[i]);
}
Then call it like
print_in_order(order, printme, [](Elem const& elem) {
std::cout << elem.a;
});
Since C++ have function overloading you can still keep the old print_in_order function for plain vectors.
Using member pointers you can implement a proxy type that will allow you view a container of objects by substituting each object by one of it's members (see pointer to data member) or by one of it's getters (see pointer to member function). The first solution addresses only data members, the second accounts for both.
The container will necessarily need to know which container to use and which member to map, which will be provided at construction. The type of a pointer to member depends on the type of that member so it will have to be considered as an additional template argument.
template<class Container, class MemberPtr>
class virtual_vector
{
public:
virtual_vector(const Container & p_container, MemberPtr p_member_ptr) :
m_container(&p_container),
m_member(p_member_ptr)
{}
private:
const Container * m_container;
MemberPtr m_member;
};
Next, implement the operator[] operator, since you mentioned that it's how you wanted to access your elements. The syntax for dereferencing a member pointer can be surprising at first.
template<class Container, class MemberPtr>
class virtual_vector
{
public:
virtual_vector(const Container & p_container, MemberPtr p_member_ptr) :
m_container(&p_container),
m_member(p_member_ptr)
{}
// Dispatch to the right get method
auto operator[](const size_t p_index) const
{
return (*m_container)[p_index].*m_member;
}
private:
const Container * m_container;
MemberPtr m_member;
};
To use this implementation, you would write something like this :
int main() {
std::vector<Elem> printme = { Elem(1,100), Elem(2,200), Elem(3,300) };
std::vector<int> order = { 2,0,1 };
virtual_vector<decltype(printme), decltype(&Elem::a)> X(printme, &Elem::a);
print_in_order(order, X);
}
This is a bit cumbersome since there is no template argument deduction happening. So lets add a free function to deduce the template arguments.
template<class Container, class MemberPtr>
virtual_vector<Container, MemberPtr>
make_virtual_vector(const Container & p_container, MemberPtr p_member_ptr)
{
return{ p_container, p_member_ptr };
}
The usage becomes :
int main() {
std::vector<Elem> printme = { Elem(1,100), Elem(2,200), Elem(3,300) };
std::vector<int> order = { 2,0,1 };
auto X = make_virtual_vector(printme, &Elem::a);
print_in_order(order, X);
}
If you want to support member functions, it's a little bit more complicated. First, the syntax to dereference a data member pointer is slightly different from calling a function member pointer. You have to implement two versions of the operator[] and enable the correct one based on the member pointer type. Luckily the standard provides std::enable_if and std::is_member_function_pointer (both in the <type_trait> header) which allow us to do just that. The member function pointer requires you to specify the arguments to pass to the function (non in this case) and an extra set of parentheses around the expression that would evaluate to the function to call (everything before the list of arguments).
template<class Container, class MemberPtr>
class virtual_vector
{
public:
virtual_vector(const Container & p_container, MemberPtr p_member_ptr) :
m_container(&p_container),
m_member(p_member_ptr)
{}
// For mapping to a method
template<class T = MemberPtr>
auto operator[](std::enable_if_t<std::is_member_function_pointer<T>::value == true, const size_t> p_index) const
{
return ((*m_container)[p_index].*m_member)();
}
// For mapping to a member
template<class T = MemberPtr>
auto operator[](std::enable_if_t<std::is_member_function_pointer<T>::value == false, const size_t> p_index) const
{
return (*m_container)[p_index].*m_member;
}
private:
const Container * m_container;
MemberPtr m_member;
};
To test this, I've added a getter to the Elem class, for illustrative purposes.
struct Elem {
int a, b;
int foo() const { return a; }
Elem(int a, int b) : a(a), b(b) {}
};
And here is how it would be used :
int main() {
std::vector<Elem> printme = { Elem(1,100), Elem(2,200), Elem(3,300) };
std::vector<int> order = { 2,0,1 };
{ // print member
auto X = make_virtual_vector(printme, &Elem::a);
print_in_order(order, X);
}
{ // print method
auto X = make_virtual_vector(printme, &Elem::foo);
print_in_order(order, X);
}
}
You've got a choice of two data structures
struct Employee
{
std::string name;
double salary;
long payrollid;
};
std::vector<Employee> employees;
Or alternatively
struct Employees
{
std::vector<std::string> names;
std::vector<double> salaries;
std::vector<long> payrollids;
};
C++ is designed with the first option as the default. Other languages such as Javascript tend to encourage the second option.
If you want to find mean salary, option 2 is more convenient. If you want to sort the employees by salary, option 1 is easier to work with.
However you can use lamdas to partially interconvert between the two. The lambda is a trivial little function which takes an Employee and returns a salary for him - so effectively providing a flat vector of doubles we can take the mean of - or takes an index and an Employees and returns an employee, doing a little bit of trivial data reformatting.
template<class F>
struct index_fake_t{
F f;
decltype(auto) operator[](std::size_t i)const{
return f(i);
}
};
template<class F>
index_fake_t<F> index_fake( F f ){
return{std::move(f)};
}
template<class F>
auto reindexer(F f){
return [f=std::move(f)](auto&& v)mutable{
return index_fake([f=std::move(f),&v](auto i)->decltype(auto){
return v[f(i)];
});
};
}
template<class F>
auto indexer_mapper(F f){
return [f=std::move(f)](auto&& v)mutable{
return index_fake([f=std::move(f),&v](auto i)->decltype(auto){
return f(v[i]);
});
};
}
Now, print in order can be rewritten as:
template <typename vectorlike>
void print(vectorlike const & printme) {
for (auto&& x:printme)
std::cout << x << std::endl;
}
template <typename vectorlike>
void print_in_order(std::vector<int> const& reorder, vectorlike const & printme) {
print(reindexer([&](auto i){return reorder[i];})(printme));
}
and printing .a as:
print_in_order( reorder, indexer_mapper([](auto&&x){return x.a;})(printme) );
there may be some typos.
I've been trying for the last three day to figure out how to implement a generic way of getting the value out of a boost::variant<...>, but it's been quite difficult.
Here is the solution I could come up with, which it not at all generic:
#include <iostream>
#include "boost\variant\variant.hpp"
using MyVariant = boost::variant<int, std::string>;
class VariantConverter : public boost::static_visitor<>
{
private:
mutable int _int;
mutable std::string _string;
static VariantConverter apply(MyVariant& v)
{
VariantConverter res;
v.apply_visitor(res);
return res; // copy will be elided, right?
}
public:
void operator()(int& i) const
{
_int = i;
}
void operator() (std::string& s) const
{
_string = s;
}
static int to_int(MyVariant v)
{
return apply(v).from_int();
}
static std::string to_string(MyVariant v)
{
return apply(v).from_string();
}
int from_int()
{
return _int;
};
std::string from_string()
{
return _string;
};
};
int main()
{
using namespace std;
MyVariant v = 23;
int i = VariantConverter::to_int(v);
cout << i << endl;
v = "Michael Jordan";
std::string s = VariantConverter::to_string(v);
cout << s.c_str() << endl;
cin.get();
return 0;
}
I'd appreciate it if someone could guide me towards a better solution.
Or perhaps someone could explain to me the rationale behind this:
if I declare a:
using MyVariant = boost::variant<int, std::string>;
and then a:
ConverterToInt : basic_visitor<int> {
public:
int operator() (int i) { return i; };
};
Why is it that when I try to apply the ConverterToInt to a MyVariant as such:
ConverterToInt cti;
MyVariant i = 10;
i.apply_visitor(cti);
I get a compiler error about trying to find a operator() that takes a std::string?
It seems to me that apply_visitor is trying to call an operator() for each of the types MyVariant can take. Is that so? If it is, why? How can i avoid this behavior?
Cheers!
You can avoid the error message by telling ConverterToInt what to do with a std::string. You might know that i can't be a std::string but it's unreasonable to expect the compiler to know that (and if it is true, why are you using a variant?).
apply_visitor will only call the correct operator() method, but it decides at run time, and the compiler needs to have all the possibilities covered to generate the code.
MyVariant iv = 10;
int i = boost::get<int>(iv);
boost::variant does not "call" each operator() of an interface when invoked, but it must be able to. That's the entire point. A variant can hold any of the template types, so if you want to define an operation on it, you must specify somewhere what that operation means for each type.
Can I use C++ template classes to differentiate object types? Or what should I use?
Eg. I have a class Synonym and it can be of type Statement, Procedure, etc for example. I have functions that accepts these synonyms and evaluates them depending on its type. So I was thinking it will be nice if I can do something like:
enum Types { Statement, Procedure, Variable, ... };
template <typename Types>
class Synonym { ... }
void evaluate(Synonym<Statement> s, Synonym<Variable> v) { do something }
^ so that I can do this ... instead of checking the type in function like:
void evaluate(Synonym s, Synonym v) {
assert(s.type == Statement);
assert(v.type == Variable);
// also would like to eliminate things like: (if possible)
switch(s.type) {
case XXX: doSomething ...
case YYY: doAnotherThing ...
}
}
You could create a function template and then specialize on that template
template<typename Type>
void evaluate (Type t) {}
template<>
void evaluate<Statement>( Statement s)
{}
This way, when you pass a Statement it will pick that overload, and you can do different behaviors depending on type.
I think using a variant and visitor pattern would be suited. Have a look at Boost.Variant here: http://www.boost.org/doc/libs/1_51_0/doc/html/variant.html, the last example (also below but expanded) shows a visitor implementation. There are also other variant and visitor implementations. std::any and loki are also options. I personally like loki but that is probably just because I'm a huge fan of Alexandrescu.
#include "boost/variant.hpp"
#include <iostream>
class ToLengthVisitor : public boost::static_visitor<int>
{
public:
int operator()(int i) const
{
return i;
}
int operator()(const std::string & str) const
{
return str.length();
}
int operator()(const char * str) const
{
const char * temp = str;
while(*temp != '\0') temp++;
return temp-str;
}
};
int main()
{
typedef boost::variant< int, std::string, const char * > MyVariant;
MyVariant u(std::string("hello world"));
std::cout << u; // output: hello world
MyVariant cu(boost::get<std::string>(u).c_str());
int result = boost::apply_visitor( ToLengthVisitor(), u );
std::cout << result; // output: 11 (i.e., length of "hello world")
result = boost::apply_visitor( ToLengthVisitor(), cu );
std::cout << result; // output: 11 (i.e., length of "hello world")
}
I need to implement an std::map with <std::string, fn_ptr> pairs. The function pointers are pointers to methods of the same class that owns the map. The idea is to have direct access to the methods instead of implementing a switch or an equivalent.
( I am using std::string as keys for the map )
I'm quite new to C++, so could anyone post some pseudo-code or link that talks about implementing a map with function pointers? ( pointers to methods owned by the same class that owns the map )
If you think there's a better approach to my problem, suggestions are also welcome.
This is about the simplest I can come up with. Note no error checking, and the map could probably usefully be made static.
#include <map>
#include <iostream>
#include <string>
using namespace std;
struct A {
typedef int (A::*MFP)(int);
std::map <string, MFP> fmap;
int f( int x ) { return x + 1; }
int g( int x ) { return x + 2; }
A() {
fmap.insert( std::make_pair( "f", &A::f ));
fmap.insert( std::make_pair( "g", &A::g ));
}
int Call( const string & s, int x ) {
MFP fp = fmap[s];
return (this->*fp)(x);
}
};
int main() {
A a;
cout << a.Call( "f", 0 ) << endl;
cout << a.Call( "g", 0 ) << endl;
}
A template implementation could look like:
class Factory {
public:
enum which {
foo, bar, baz
};
template<which w>
A* newA(...);
...
};
template<Factory::which w>
A* Factory::newA(...) {
/* default implementation */
throw invalid_argument();
}
template<>
A* Factory::newA<Factory::foo>(...) {
/* specialization for a 'foo' style A */
...
}
....
This requires that the value used to determine which newA is called be known at compile time. You could potentially use a const char * as the template parameter, but it's not guaranteed to work on all compilers.
Yet another option is to create helper factories, one for each factory creation method, and store those in the map. This isn't a huge advantage over storing method pointers, but does let you define a default creation method and simplifies fetching things from the map (there's no need to check that the key exists, because you'll get a default factory). On the downside, an entry for each unknown key would be added to the map.
Also, if you use an enum rather than a string for the key type, you shouldn't need to worry about checking whether a key exists in the map. While it's possible for someone to pass an invalid enum key to newA, they'd have to explicitly cast the argument, which means they're not going to do it by accident. I'm having a hard time imagining a case where someone would purposefully cause a crash in newA; the potential scenarios involve security, but an application programmer could crash the app without using your class.
Since C++14, we can use a generic lambda to get rid easily of pointers to member methods.
It follows a minimal, working example of a forward function made up with a generic lambda function:
#include<utility>
#include<map>
#include<string>
#include<iostream>
struct SomeClass { };
struct SomeOtherClass { };
struct Test {
void test(SomeClass) { std::cout << "SomeClass" << std::endl; }
void test(SomeOtherClass) { std::cout << "SomeOtherClass" << std::endl; }
};
int main() {
Test test;
auto l = [&test](auto c){ test.test(c); };
std::map<std::string, decltype(l)> m;
m.emplace("foo", l);
m.emplace("bar", l);
m.at("foo")(SomeClass{});
m.at("bar")(SomeOtherClass{});
}
Another option is to use delegates as oppose to function pointers. This delegate implementation is pretty fast, supports polymorphisms, and plays well with stl containers.
You could have something like:
class MyClass {
public:
// defines
typedef fastdelegate::FastDelegate2<int, int, int> MyDelegate;
typedef std::map<std::string, MyDelegate> MyMap;
// populate your map of delegates
MyClass() {
_myMap["plus"] = fastdelegate::MakeDelegate(this, &Plus);
_myMap["minus"] = fastdelegate::MakeDelegate(this, &Minus);
}
bool Do(const std::string& operation, int a, int b, int& res){
MyMap::const_iterator it = _myMap.find(operation);
if (it != _myMap.end()){
res = it.second(a,b);
return true;
}
return false;
}
private:
int Plus (int a, int b) { return a+b; }
int Minus(int a, int b) { return a-b; }
MyMap _myMap;
};