I've come to a pattern when writing enums in C++. It is like this:
class Player
{
public:
class State
{
public:
typedef enum
{
Stopped,
Playing,
Paused
}PossibleValues;
static const int Count() {return Paused+1;};
static const PossibleValues Default() {return Stopped;};
};
//...
}
This solves a some of the usual issues with enums, like pollution of outside namespaces, etc. But there is still a thing I don't like: The Count() is done manually. There are only two ways I know how to do it: this one is calculated from Last+1; or write plain hardcoded.
Question is: Is there some way, like using preprocessor macros, that automatically gets the count, to put it after in the Count() method? Attention: I don't want to have a last fake element called Count inside the enum, polluting it!
Thanks in advance!
UPDATE 1:
There is an interesting discussion on Implementation of N4428 enum reflection in standard C++11 (partial) for a proposal of more advanced enums.
UPDATE 2:
Interesting document N4451- Static reflection (rev. 3) on its sections 3.16, 3.17, A.7, A.8 about MetaEnums and MetaEnumClasses.
UPDATE 3:
I came to another interesting pattern using an enum class, after I've seen https://bytes.com/topic/c/answers/127908-numeric_limits-specialization#post444962. If the enum class's enumerator list is continuously integer, by defining its maximum and its minimum, we can check whether a value belongs to it or not.
If the purpose of using the Count() method on the Player::State was to check if a value was in the enum, that purpose has also been achieved with the numeric_limits approach, and is even superior, as it is not required the enumerator list begins with a ZERO valued item!
enum class Drink
{
Water,
Beer,
Wine,
Juice,
};
#pragma push_macro("min")
#undef min
#pragma push_macro("max")
#undef max
namespace std
{
template <> class numeric_limits < Drink >
{
public:
static const/*expr*/ bool is_specialized = true;
static const/*expr*/ Drink min() /*noexcept*/ { return Drink::Water; }
static const/*expr*/ Drink max() /*noexcept*/ { return Drink::Juice; }
static const/*expr*/ Drink lowest() /*noexcept*/ { return Drink::Water; }
static const/*expr*/ Drink default() /*noexcept*/ { return Drink::Beer; }
};
}
#pragma pop_macro("min")
#pragma pop_macro("max")
CASES OF USE:
A variable from the application:
Drink m_drink;
which in constructor is initialized with:
m_drink = numeric_limits<Drink>::default();
On the initialization of a form, I can do:
pComboDrink->SetCurSel(static_cast<int>(theApp.m_drink));
On it, for adapting the interface to changes done by the user, I can do a switch with scoped enum class values:
switch (static_cast<Drink>(pComboDrink->GetCurSel()))
{
case Drink::Water:
case Drink::Juice:
pAlcohoolDegreesControl->Hide();
break;
case Drink::Beer:
case Drink::Wine:
pAlcohoolDegreesControl->Show();
break;
default:
break;
}
And on the dialog's confirmation procedure (OnOK), I can check if the value is out of boundaries, before saving it to the respective app var:
int ix= pComboDrink->GetCurSel();
if (ix == -1)
return FALSE;
#pragma push_macro("min")
#undef min
#pragma push_macro("max")
#undef max
if (ix < static_cast<int> (std::numeric_limits<Drink>::min()) || ix > static_cast<int> (std::numeric_limits<Drink>::max()) )
return FALSE;
#pragma pop_macro("min")
#pragma pop_macro("max")
theApp.m_drink= static_cast<Drink>(ix);
NOTES:
The keywords constexpr (I commented /*expr*/, leaving it as const ) and noexcept are commented only because the compiler I am using (Visual C++ 2013) does not support them yet at the current version.
Maybe you do not need the logic to temporary undefine the min and max macros.
I know that the default() does not fit on a "numeric limits" scope; but it seemed an handy place to put it on; even it coincides with the default word that in some contexts is a keyword!
No there isn't, and if you need this, you probably shouldn't be using an enum in the first place.
In your particular case, what's a use case where you'd ever want to call Count?
AFAIK there's no automatic compiler-supported keyword to get the total amount of elements in enum. OTOH this usually doesn't make sense: you may have multiple values with the same value, as long as the values don't have to have consequent values (i.e. you may assign the values manually, rather than rely on automatic numbering).
One common practice is to declare the enum in the following way:
typedef enum
{
Stopped,
Playing,
Paused,
count
}PossibleValues;
This way, if count is always defined last - it will give you the count of the enum elements, assuming the numbering starts from 0 and is consequent.
Reposting an answer from a similar question (What is the best way for non sequencial integer c++ enums) because it was kind of relevant to an otherwise pretty much unanswered question.
A pattern you could use to get what you want is to use an std::initializer_list to store all the values of your enum.
namespace PossibleValues
{
enum Type
{
ZERO= 0,
PLUS180= 180,
PLUS90= 90,
MINUS90= -90
};
constexpr auto Values = {ZERO, PLUS180, PLUS90, MINUS90};
size_t Count() { return Values.size(); }
Type Default() { return *begin(Values); }
}
This also has the benefit of being able to iterate of the values of the enum even if they don't have linear values.
And I think you could possibly generate both the enum, the initializer list and the functions from a single macro with a variadic macro, though in the best of worlds this kind of thing should be in the standard.
Edit: When I used PossibleValues as an enum or used a struct for PossibleValues, my compiler would complain about incomplete type. Using a namespace for an enum is a bit unusual, but it works fine.
The solution from https://stackoverflow.com/a/60216003/12894563 can be improved. We can save enums expressions in a static vector and iterate, obtain min/max and etc
Usage:
#include <type_traits>
#include <algorithm>
#include <vector>
#include <iostream>
#define make_enum(Name, Type, ...) \
struct Name { \
enum : Type { \
__VA_ARGS__ \
}; \
static auto count() { return values.size(); } \
\
static inline const std::vector<Type> values = [] { \
static Type __VA_ARGS__; return std::vector<Type>({__VA_ARGS__}); \
}(); \
static Type min() \
{ \
static const Type result = *std::min_element(values.begin(), values.end()); \
return result; \
} \
static Type max() \
{ \
static const Type result = *std::max_element(values.begin(), values.end()); \
return result; \
} \
}
make_enum(FakeEnum, int, A = 1, B = 0, C = 2, D);
int main(int argc, char *argv[])
{
std::cout << FakeEnum::A << std::endl
<< FakeEnum::min() << std::endl
<< FakeEnum::max() << std::endl
<< FakeEnum::count() << std::endl;
return 0;
}
Must the type of PossibleValues be an enum? If you just need something that behaves like an enum, you can do the following:
#include <iostream>
#include <functional>
#include <set>
template <typename Representation, typename T>
class Iterable_Strong_Enum
{
private:
struct T_Ptr_Less : public std::binary_function<T const *, T const *, bool>
{
bool operator()(T const * x, T const * y) const
{
return x->get_representation() < y->get_representation();
}
};
public:
typedef std::set<T const *, T_Ptr_Less> instances_list;
typedef typename instances_list::const_iterator const_iterator;
Representation const & get_representation() const { return _value; }
static Representation const & min() { return (*_instances.begin())->_value; }
static Representation const & max() { return (*_instances.rbegin())->_value; }
static T const * corresponding_enum(Representation const & value)
{
const_iterator it = std::find_if(_instances.begin(), _instances.end(), [&](T const * e) -> bool
{
return e->get_representation() == value;
});
if (it != _instances.end())
{
return *it;
}
else
{
return nullptr;
}
}
bool operator==(T const & other) const { return _value == other._value; }
bool operator!=(T const & other) const { return _value != other._value; }
bool operator< (T const & other) const { return _value < other._value; }
bool operator<=(T const & other) const { return _value <= other._value; }
bool operator> (T const & other) const { return _value > other._value; }
bool operator>=(T const & other) const { return _value >= other._value; }
static bool is_valid_value(Representation const & value) { return corresponding_enum(value) != nullptr; }
static typename instances_list::size_type size() { return _instances.size(); }
static const_iterator begin() { return _instances.begin(); }
static const_iterator end() { return _instances.end(); }
protected:
explicit Iterable_Strong_Enum(Representation const & value);
private:
Representation _value;
static instances_list _instances;
};
template <typename Representation, typename T>
Iterable_Strong_Enum<Representation, T>::Iterable_Strong_Enum(Representation const & value)
: _value(value)
{
_instances.insert(static_cast<T const *>(this));
}
class PossibleValues : public Iterable_Strong_Enum<int, PossibleValues>
{
public:
static const PossibleValues Stopped;
static const PossibleValues Playing;
static const PossibleValues Pause;
protected:
private:
explicit PossibleValues(int value);
};
PossibleValues::PossibleValues(int value) : Iterable_Strong_Enum<int, PossibleValues>(value) { }
// you need to call that explicitly
Iterable_Strong_Enum<int, PossibleValues>::instances_list Iterable_Strong_Enum<int, PossibleValues>::_instances;
const PossibleValues PossibleValues::Stopped(0);
const PossibleValues PossibleValues::Playing(1);
const PossibleValues PossibleValues::Pause(2);
void stackoverflow()
{
std::cout << "There are " << PossibleValues::size() << " different possible values with representation: " << std::endl;
for (auto pv = PossibleValues::begin(); pv != PossibleValues::end(); ++pv)
{
PossibleValues possible_value = **pv;
std::cout << possible_value.get_representation() << std::endl;
}
}
I'm kinda torn about that solution. On the one hand, its pretty general and on the other hand its a big hammer for a small problem.
Related
I'm trying to make a list of template classes of variable types. So the idea is to loop of a list of objects that all have a common function, e.g. getValue, but a different type. The type could be any type, raw types or objects.
I need this because i want to have a class that has a list of attributes of different types that i want to be able to construct at runtime.
So my class would look something like:
class MyClass {
std::list<Attribute<?>*> attributes;
};
And my attribute template:
template<typename T>
class Attribute {
public:
Test(const T &t) : _t(t) {}
T getValue() const { return _t; }
void setValue(const T &t) { _t = t; }
private:
T _t;
};
int main() {
MyClass myClass;
myClass.attributes.push_back(new Attribute<int>(42));
myClass.attributes.push_back(new Attribute<double>(42.0));
}
As you can see the list of MyClass i put ? because that is my problem. I dont know how to make a list that will take different types of my Attribute template, i.e. int, double etc.
std::list<Attribute<?> *> attributes;
In Java, generics can be used for that. Is it possible in C++ to do this with somekind of construction? I tried using variadic templates but that doesnt seem to help solving my problem.
I need this but not in Java, in C++:
public class GenericAttribute<T> {
private T value;
public GenericAttribute (T value) {
setValue(value);
}
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
}
public static void main(String[] args) {
class Custom {
public Custom() {}
#Override public String toString() {
return "My custom object";
}
}
List<GenericAttribute<?>> attributes = new ArrayList<GenericAttribute<?>>();
attributes.add(new GenericAttribute<Integer>(1));
attributes.add(new GenericAttribute<Double>(3.1415926535));
attributes.add(new GenericAttribute<Custom>(new Custom()));
for (GenericAttribute<?> attr : attributes) {
System.out.println(attr.getValue());
}
}
Output:
1
3.1415926535
My custom object
Thanks for the help!
Version 3: Very Advanced (do not try that at home :D)
class Attribute {
private:
struct Head {
virtual ~Head() {}
virtual void *copy() = 0;
const type_info& type;
Head(const type_info& type): type(type) {}
void *data() { return this + 1; }
};
template <class T> struct THead: public Head {
THead(): Head(typeid(T)) {}
virtual ~THead() override { ((T*)data())->~T(); }
virtual void *copy() override {
return new(new(malloc(sizeof(Head) + sizeof(T)))
THead() + 1) T(*(const T*)data()); }
};
void *data;
Head *head() const { return (Head*)data - 1; }
void *copy() const { return data ? head()->copy() : nullptr; }
public:
Attribute(): data(nullptr) {}
Attribute(const Attribute& src): data(src.copy()) {}
Attribute(Attribute&& src): data(src.data) { src.data = nullptr; }
template <class T> Attribute(const T& src): data(
new(new(malloc(sizeof(Head) + sizeof(T))) THead<T>() + 1) T(src)) {}
~Attribute() {
if(!data) return;
Head* head = this->head();
head->~Head(); free(head); }
bool empty() const {
return data == nullptr; }
const type_info& type() const {
assert(data);
return ((Head*)data - 1)->type; }
template <class T>
T& value() {
if (!data || type() != typeid(T))
throw bad_cast();
return *(T*)data; }
template <class T>
const T& value() const {
if (!data || type() != typeid(T))
throw bad_cast();
return *(T*)data; }
template <class T>
void setValue(const T& it) {
if(!data)
data = new(new(malloc(sizeof(Head) + sizeof(T)))
THead<T>() + 1) T(it);
else {
if (type() != typeid(T)) throw bad_cast();
*(T*)data = it; }}
public:
static void test_me() {
vector<Attribute> list;
list.push_back(Attribute(1));
list.push_back(3.14);
list.push_back(string("hello world"));
list[1].value<double>() = 3.141592;
list.push_back(Attribute());
list[3].setValue(1.23f);
for (auto& a : list) {
cout << "type = " << a.type().name()
<< " value = ";
if(a.type() == typeid(int)) cout << a.value<int>();
else if (a.type() == typeid(double)) cout << a.value<double>();
else if (a.type() == typeid(string)) cout << a.value<string>();
else if (a.type() == typeid(float)) cout << a.value<float>();
cout << endl;
}
}
};
Output:
type = i value = 1
type = d value = 3.14159
type = Ss value = hello world
type = f value = 1.23
Explanation:
Attribute contains data pointer, which is initializaed by this strange placement new: new(new(malloc(sizeof(Head) + sizeof(T))) THead<T>() + 1) T(src) which first allocates enough room for the Head (should be 2*sizeof(void*) which should be just fine for any allignment of any architecture) and the type itself, constructs THead<T>() (initializes pointer to virtual method table and type info) and moves the pointer after the head = at the place we want data. The object is then constructed by another placement new using copy-constructor (or move-constructor) T(src). struct Head has two virtual functions - destructor and copy() which is implemented in THead<T> and used in Attribute(const Attribute&) copy-constructor. Finally ~Attribute() destructor calls ~Head() virtual destructor and releases the memory (if data != nullptr).
Version 1: Simple Attribute List
#include <vector>
#include <typeinfo>
#include <iostream>
#include <cstdlib>
#include <new>
using namespace std;
class Attributes {
public:
typedef pair<const type_info&,void*> value_type;
typedef vector<value_type> vect;
typedef vect::const_iterator const_iterator;
template <class T>
void add(const T& value) {
data.push_back(pair<const type_info&,void*>(
typeid(T), new(malloc(sizeof(T))) T(value))); }
const_iterator begin() const {
return data.begin(); }
const_iterator end() const {
return data.end(); }
private:
vect data;
} attrs;
int main() {
attrs.add(1);
attrs.add(3.14);
for (auto a : attrs) {
cout << a.first.name() << " = ";
if(a.first == typeid(int))
cout << *(int*)a.second;
else if(a.first == typeid(double))
cout << *(double*)a.second;
cout << endl;
}
}
Output:
i = 1
d = 3.14
Version 2 (named attributes):
#include <string>
#include <unordered_map>
#include <typeinfo>
#include <iostream>
#include <cstdlib>
#include <new>
using namespace std;
class Attributes {
public:
typedef pair<const type_info&,void*> value_type;
typedef unordered_map<string,value_type> map;
typedef map::const_iterator const_iterator;
template <class T>
bool add(const string& name, const T& value) {
auto it = data.insert(make_pair(
name, value_type(typeid(T), nullptr)));
if (!it.second) return false;
it.first->second.second = new(malloc(sizeof(T))) T(value);
return true; }
template <class T>
const T& get(const string& name) const {
auto it = data.at(name);
if (it.first != typeid(T)) throw bad_cast();
return *(T*)it.second; }
const_iterator begin() const {
return data.begin(); }
const_iterator end() const {
return data.end(); }
void erase(const_iterator it) {
free(it->second.second);
data.erase(it); }
bool remove(const string& name) {
auto it = data.find(name);
if (it == data.end()) return false;
free(it->second.second);
data.erase(it);
return true; }
private:
map data;
} attrs;
int main() {
attrs.add("one", 1);
attrs.add("pi", 3.14);
cout << "pi = " << attrs.get<double>("pi") << endl;
attrs.remove("pi");
for (auto a : attrs) {
cout << a.first << " = ";
if(a.second.first == typeid(int))
cout << *(int*)a.second.second;
else if(a.second.first == typeid(double))
cout << *(double*)a.second.second;
cout << endl;
}
}
Take a look at variant - this is a class that can be one of a number of different types, but you don't mind which until you need to operate on the values, in which case you can use the visitor pattern to visit all the types.
It is effectively a C++ type-aware version of the C 'union' construct but as it 'knows' which type was set, it can offer type safety.
The biggest issue with variants is that if you expose your implementation and allow any client to put pretty much any type into your variant (attributes.push_back(new Attribute<Widget>(myWidget));), you're going to be unable to do anything with it. E.g. if you want to do 'sum' on all the values put into your attributes, you'd need them to be convertible to a numeric representation and a Widget might not be.
The bigger question is what are you trying to do with them once you've captured these items as Attributes? Enumerating through them calling getValue() is going to give you different results depending on what types you put in. A visitor object would work, but it's still not clear what value this would bring.
It could be that you need something different, such as an interface, e.g. IAttribute that abstracts the underlying type as long as it conforms to the interface which has a getValueAsDouble() method or getValueAsString() method, which you could do to any type that got passes in - no need for variant or visitor in this case.
As Attribute<int> is different type than Attribute<double>, you can't use list or vector without creating a common base type.
Alternatively, you may store different type into a std::tuple.
Following may help:
template <typename ... Ts>
class MyClass {
public:
MyClass(const Ts&... args) : attributes(args...) {}
private:
std::tuple<Attribute<Ts>...> attributes;
};
int main()
{
MyClass<int, double> myClass(42, 42.0);
return 0;
}
As you already pointed out, in java it is much easier to do so because all classes extends java.lang.Object. In C(++), there is a similar way, but only for pointers - you can use void* for this. Your list will look something like this then:
std::list<Attribute<void*> *> attributes;
Sure, a void* doesn't save the type. If you need, add this field to your Attribute-class:
public:
std::type_info type;
Then, if you create an instance of Attributre, do this (probably from the constructor):
type = typeinfo(type_to_store);
Of corse, if you do so from the constructor, you'll need to run typeinfo in the code that calls the constructor.
Then, you can get the name of the class back from that field and the instance back from your void*:
std::string name = attribute->type_info.name();
void * instance = attribute->getValue();
What operations do you want to perform on this collection? Do you want to, say, call getValue on all of the Attribute<int> instances and ignore the others? In that case, a base class is fine—you just don’t make the getValue member function virtual (because its type depends on the subclass) and use RTTI to recover the type information at runtime:
struct AnyAttribute {
// Needs at least one virtual function to support dynamic_cast.
virtual ~AnyAttribute() {}
};
template<typename T>
struct Attribute : AnyAttribute { … };
int main() {
std::vector<AnyAttribute*> attributes;
attributes.push_back(new Attribute<int>(13));
attributes.push_back(new Attribute<int>(42));
attributes.push_back(new Attribute<double>(2.5));
for (const auto attribute : attributes) {
if (const auto int_attribute = dynamic_cast<Attribute<int>>(attribute)) {
std::cout << int_attribute->getValue() << '\n';
}
}
}
An obvious, but naive solution will be:
inherit Attribute<T> from base AttributeBase
store AttributeBase (smart-)pointers in container (downcast)
when reading container element, somehow figure out its type (RTTI)
cast back to derived Attribute<T> (upcast)
You can beautify this ugly solution by adding another level of indirection: make a generic container, that stores generic containers for each attribute, so casting will happen under the hood.
You can use integrated to language RTTI features, such as type_info but as far as I know, it's reliability is questionable. Better solution will be to wrap up some kind of static unique id to each Attribute<T> class and put an accessor to AttributeBase to retrieve it. You can add a typedef to relevant Attribute<T> to your unique id class to make casting easier.
So far so good, but in modern C++, we know, that when you need RTTI, it, probably, means that there is something wrong with your overall code design.
I don't know what exact task you have, but my "gut feelings" say me that you will probably can eliminate need of RTTI by using multiple dispatch (double dispatch), such as Visitor pattern in your code (they always say that when see RTTI).
Also, check some other tricks for inspiration:
More C++ Idioms/Coercion by Member Template
I am using a container to hold a list of pointers to anything:
struct Example {
std::vector<boost::any> elements;
}
To insert elements in this container, I had written a couple of helper functions (members of the struct Example):
void add_any(boost::any& a) {
elements.push_back(a);
}
template<typename T>
void add_to_list(T& a) {
boost::any bany = &a;
add_any(bany);
}
Now, I would like to insert elements only when they are not present in this container. To do this, I thought that I would only need to call search over elements with an appropriate comparator function. However, I do not know how to compare the boost::any instances.
My question:
Knowing that my boost::any instances always contain a pointer to something; is it possible to compare two boost::any values?
update
I thank you for your answers. I have also managed to do this in a probably unsafe way: using boost::unsafe_any_cast to obtain a void** and comparing the underlying pointer.
For the moment, this is working fine. I would, however, appreciate your comments: maybe this is a big mistake!
#include <boost/any.hpp>
#include <iostream>
#include <vector>
#include <string>
using namespace std;
bool any_compare(const boost::any& a1, const boost::any& a2) {
cout << "compare " << *boost::unsafe_any_cast<void*>(&a1)
<< " with: " << *boost::unsafe_any_cast<void*>(&a2);
return (*boost::unsafe_any_cast<void*>(&a1)) ==
(*boost::unsafe_any_cast<void*>(&a2));
}
struct A {};
class Example {
public:
Example() : elements(0),
m_1(3.14),
m_2(42),
m_3("hello"),
m_4() {};
virtual ~Example() {};
void test_insert() {
add_to_list(m_1);
add_to_list(m_2);
add_to_list(m_3);
add_to_list(m_4);
add_to_list(m_1); // should not insert
add_to_list(m_2); // should not insert
add_to_list(m_3); // should not insert
add_to_list(m_4); // should not insert
};
template <typename T>
void add_to_list(T& a) {
boost::any bany = &a;
add_any(bany);
}
private:
vector<boost::any> elements;
double m_1;
int m_2;
string m_3;
A m_4;
void add_any(const boost::any& a) {
cout << "Trying to insert " << (*boost::unsafe_any_cast<void*>(&a)) << endl;
vector<boost::any>::const_iterator it;
for (it = elements.begin();
it != elements.end();
++it) {
if ( any_compare(a,*it) ) {
cout << " : not inserting, already in list" << endl;
return;
}
cout << endl;
}
cout << "Inserting " << (*boost::unsafe_any_cast<void*>(&a)) << endl;
elements.push_back(a);
};
};
int main(int argc, char *argv[]) {
Example ex;
ex.test_insert();
unsigned char c;
ex.add_to_list(c);
ex.add_to_list(c); // should not insert
return 0;
}
You cannot directly provide it, but you can actually use any as the underlying type... though for pointers it's pointless (ah!)
struct any {
std::type_info const& _info;
void* _address;
};
And a templated constructor:
template <typename T>
any::any(T* t):
_info(typeid(*t)),
_address(dynamic_cast<void*>(t))
{
}
This is, basically, boost::any.
Now we need to "augment" it with our comparison mechanism.
In order to do so, we'll "capture" the implementation of std::less.
typedef bool (*Comparer)(void*,void*);
template <typename T>
bool compare(void* lhs, void* rhs) const {
return std::less<T>()(*reinterpret_cast<T*>(lhs), *reinterpret_cast<T*>(rhs));
}
template <typename T>
Comparer make_comparer(T*) { return compare<T>; }
And augment the constructor of any.
struct any {
std::type_info const& _info;
void* _address;
Comparer _comparer;
};
template <typename T>
any::any(T* t):
_info(typeid(*t)),
_address(dynamic_cast<void*>(t)),
_comparer(make_comparer(t))
{
}
Then, we provided a specialization of less (or operator<)
bool operator<(any const& lhs, any const& rhs) {
if (lhs._info.before(rhs._info)) { return true; }
if (rhs._info.before(lhs._info)) { return false; }
return (*lhs._comparer)(lhs._address, rhs._address);
}
Note: encapsulation, etc... are left as an exercise to the reader
The only easy way to do this I can think of involves hardcoding support for the types that you're storing in the any instances, undermining much of the usefulness of any...
bool equal(const boost::any& lhs, const boost::any& rhs)
{
if (lhs.type() != rhs.type())
return false;
if (lhs.type() == typeid(std::string))
return any_cast<std::string>(lhs) == any_cast<std::string>(rhs);
if (lhs.type() == typeid(int))
return any_cast<int>(lhs) == any_cast<int>(rhs);
// ...
throw std::runtime_error("comparison of any unimplemented for type");
}
With C++11's type_index you could use a std::map or std::unordered_map keyed on std::type_index(some_boost_any_object.type()) - similar to what Alexandre suggests in his comment below.
If you can change type in container, there is Boost.TypeErasure. It provides easy way to customize any. For example I'm using such typedef for similar purpose:
#include <boost/type_erasure/any.hpp>
#include <boost/type_erasure/operators.hpp>
using Foo = boost::type_erasure::any<
boost::mpl::vector<
boost::type_erasure::copy_constructible<>,
boost::type_erasure::equality_comparable<>,
boost::type_erasure::typeid_<>,
boost::type_erasure::relaxed
>
>;
Foo behaves exactly the same as boost::any, except that it can be compared for equality and use boost::type_erasure::any_cast instead of boost::any_cast.
There is no need to create new class. Try to use xany https://sourceforge.net/projects/extendableany/?source=directory xany class allows to add new methods to any's existing functionality. By the way there is a example in documentation which does exactly what you want (creates comparable_any).
Maybe this algorithm come in handy >
http://signmotion.blogspot.com/2011/12/boostany.html
Compare two any-values by type and content. Attempt convert string to number for equals.
I was searching for an implementation of extension methods in c++ and came upon this comp.std.c++ discussion which mentions that polymorphic_map can be used to associated methods with a class, but, the provided link seems to be dead. Does anyone know what that answer was referring to, or if there is another way to extend classes in a similar manner to extension methods (perhaps through some usage of mixins?).
I know the canonical C++ solution is to use free functions; this is more out of curiosity than anything else.
Different languages approach development in different ways. In particular C# and Java have a strong point of view with respect to OO that leads to everything is an object mindset (C# is a little more lax here). In that approach, extension methods provide a simple way of extending an existing object or interface to add new features.
There are no extension methods in C++, nor are they needed. When developing C++, forget the everything is an object paradigm --which, by the way, is false even in Java/C# [*]. A different mindset is taken in C++, there are objects, and the objects have operations that are inherently part of the object, but there are also other operations that form part of the interface and need not be part of the class. A must read by Herb Sutter is What's In a Class?, where the author defends (and I agree) that you can easily extend any given class with simple free functions.
As a particular simple example, the standard templated class basic_ostream has a few member methods to dump the contents of some primitive types, and then it is enhanced with (also templated) free functions that extend that functionality to other types by using the existing public interface. For example, std::cout << 1; is implemented as a member function, while std::cout << "Hi"; is a free function implemented in terms of other more basic members.
Extensibility in C++ is achieved by means of free functions, not by ways of adding new methods to existing objects.
[*] Everything is not an object.
In a given domain will contain a set of actual objects that can be modeled and operations that can be applied to them, in some cases those operations will be part of the object, but in some other cases they will not. In particular you will find utility classes in the languages that claim that everything is an object and those utility classes are nothing but a layer trying to hide the fact that those methods don't belong to any particular object.
Even some operations that are implemented as member functions are not really operations on the object. Consider addition for a Complex number class, how is sum (or +) more of an operation on the first argument than the second? Why a.sum(b); or b.sum(a), should it not be sum( a, b )?
Forcing the operations to be member methods actually produces weird effects --but we are just used to them: a.equals(b); and b.equals(a); might have completely different results even if the implementation of equals is fully symmetric. (Consider what happens when either a or b is a null pointer)
Boost Range Library's approach use operator|().
r | filtered(p);
I can write trim for string as follows in the same way, too.
#include <string>
namespace string_extension {
struct trim_t {
std::string operator()(const std::string& s) const
{
...
return s;
}
};
const trim_t trim = {};
std::string operator|(const std::string& s, trim_t f)
{
return f(s);
}
} // namespace string_extension
int main()
{
const std::string s = " abc ";
const std::string result = s | string_extension::trim;
}
This is the closest thing that I have ever seen to extension methods in C++. Personally i like the way it can be used, and possibly this it the closest we can get to extension methods in this language. But there are some disadvantages:
It may be complicated to implement
Operator precedence may be not that nice some times, this may cause surprises
A solution:
#include <iostream>
using namespace std;
class regular_class {
public:
void simple_method(void) const {
cout << "simple_method called." << endl;
}
};
class ext_method {
private:
// arguments of the extension method
int x_;
public:
// arguments get initialized here
ext_method(int x) : x_(x) {
}
// just a dummy overload to return a reference to itself
ext_method& operator-(void) {
return *this;
}
// extension method body is implemented here. The return type of this op. overload
// should be the return type of the extension method
friend const regular_class& operator<(const regular_class& obj, const ext_method& mthd) {
cout << "Extension method called with: " << mthd.x_ << " on " << &obj << endl;
return obj;
}
};
int main()
{
regular_class obj;
cout << "regular_class object at: " << &obj << endl;
obj.simple_method();
obj<-ext_method(3)<-ext_method(8);
return 0;
}
This is not my personal invention, recently a friend of mine mailed it to me, he said he got it from a university mailing list.
The short answer is that you cannot do that. The long answer is that you can simulate it, but be aware that you'll have to create a lot of code as workaround (actually, I don't think there is an elegant solution).
In the discussion, a very complex workaround is provided using operator- (which is a bad idea, in my opinion). I guess that the solution provided in the dead link was more o less similar (since it was based on operator|).
This is based in the capability of being able to do more or less the same thing as an extension method with operators. For example, if you want to overload the ostream's operator<< for your new class Foo, you could do:
class Foo {
friend ostream &operator<<(ostream &o, const Foo &foo);
// more things...
};
ostream &operator<<(ostream &o, const Foo &foo)
{
// write foo's info to o
}
As I said, this is the only similar mechanism availabe in C++ for extension methods. If you can naturally translate your function to an overloaded operator, then it is fine. The only other possibility is to artificially overload an operator that has nothing to do with your objective, but this is going to make you write very confusing code.
The most similar approach I can think of would mean to create an extension class and create your new methods there. Unfortunately, this means that you'll need to "adapt" your objects:
class stringext {
public:
stringext(std::string &s) : str( &s )
{}
string trim()
{ ...; return *str; }
private:
string * str;
};
And then, when you want to do that things:
void fie(string &str)
{
// ...
cout << stringext( str ).trim() << endl;
}
As said, this is not perfect, and I don't think that kind of perfect solution exists.
Sorry.
To elaborate more on #Akira answer, operator| can be used to extend existing classes with functions that take parameters too. Here an example that I'm using to extend Xerces XML library with find functionalities that can be easily concatenated:
#pragma once
#include <string>
#include <stdexcept>
#include <xercesc/dom/DOMElement.hpp>
#define _U16C // macro that converts string to char16_t array
XERCES_CPP_NAMESPACE_BEGIN
struct FindFirst
{
FindFirst(const std::string& name);
DOMElement * operator()(const DOMElement &el) const;
DOMElement * operator()(const DOMElement *el) const;
private:
std::string m_name;
};
struct FindFirstExisting
{
FindFirstExisting(const std::string& name);
DOMElement & operator()(const DOMElement &el) const;
private:
std::string m_name;
};
inline DOMElement & operator|(const DOMElement &el, const FindFirstExisting &f)
{
return f(el);
}
inline DOMElement * operator|(const DOMElement &el, const FindFirst &f)
{
return f(el);
}
inline DOMElement * operator|(const DOMElement *el, const FindFirst &f)
{
return f(el);
}
inline FindFirst::FindFirst(const std::string & name)
: m_name(name)
{
}
inline DOMElement * FindFirst::operator()(const DOMElement &el) const
{
auto list = el.getElementsByTagName(_U16C(m_name));
if (list->getLength() == 0)
return nullptr;
return static_cast<DOMElement *>(list->item(0));
}
inline DOMElement * FindFirst::operator()(const DOMElement *el) const
{
if (el == nullptr)
return nullptr;
auto list = el->getElementsByTagName(_U16C(m_name));
if (list->getLength() == 0)
return nullptr;
return static_cast<DOMElement *>(list->item(0));
}
inline FindFirstExisting::FindFirstExisting(const std::string & name)
: m_name(name)
{
}
inline DOMElement & FindFirstExisting::operator()(const DOMElement & el) const
{
auto list = el.getElementsByTagName(_U16C(m_name));
if (list->getLength() == 0)
throw runtime_error(string("Missing element with name ") + m_name);
return static_cast<DOMElement &>(*list->item(0));
}
XERCES_CPP_NAMESPACE_END
It can be used this way:
auto packetRate = *elementRoot | FindFirst("Header") | FindFirst("PacketRate");
auto &decrypted = *elementRoot | FindFirstExisting("Header") | FindFirstExisting("Decrypted");
You can enable kinda extension methods for your own class/struct or for some specific type in some scope. See rough solution below.
class Extensible
{
public:
template<class TRes, class T, class... Args>
std::function<TRes(Args...)> operator|
(std::function<TRes(T&, Args...)>& extension)
{
return [this, &extension](Args... args) -> TRes
{
return extension(*static_cast<T*>(this), std::forward<Args>(args)...);
};
}
};
Then inherit your class from this and use like
class SomeExtensible : public Extensible { /*...*/ };
std::function<int(SomeExtensible&, int)> fn;
SomeExtensible se;
int i = (se | fn)(4);
Or you can declare this operator in cpp file or namespace.
//for std::string, for example
template<class TRes, class... Args>
std::function<TRes(Args...)> operator|
(std::string& s, std::function<TRes(std::string&, Args...)>& extension)
{
return [&s, &extension](Args... args) -> TRes
{
return extension(s, std::forward<Args>(args)...);
};
}
std::string s = "newStr";
std::function<std::string(std::string&)> init = [](std::string& s) {
return s = "initialized";
};
(s | init)();
Or even wrap it in macro (I know, it's generally bad idea, nevertheless you can):
#define ENABLE_EXTENSIONS_FOR(x) \
template<class TRes, class... Args> \
std::function<TRes(Args...)> operator| (x s, std::function<TRes(x, Args...)>& extension) \
{ \
return [&s, &extension](Args... args) -> TRes \
{ \
return extension(s, std::forward<Args>(args)...); \
}; \
}
ENABLE_EXTENSIONS_FOR(std::vector<int>&);
This syntactic sugar isn't available in C++, but you can define your own namespace and write pure static classes, using const references as the first parameter.
For example, I was struggling using the STL implementation for some array operations, and I didn't like the syntaxis, I was used to JavaScript's functional way of how array methods worked.
So, I made my own namespace wh with the class vector in it, since that's the class I was expecting to use these methods, and this is the result:
//#ifndef __WH_HPP
//#define __WH_HPP
#include <vector>
#include <functional>
#include <algorithm>
namespace wh{
template<typename T>
class vector{
public:
static T reduce(const std::vector<T> &array, const T &accumulatorInitiator, const std::function<T(T,T)> &functor){
T accumulator = accumulatorInitiator;
for(auto &element: array) accumulator = functor(element, accumulator);
return accumulator;
}
static T reduce(const std::vector<T> &array, const T &accumulatorInitiator){
return wh::vector<T>::reduce(array, accumulatorInitiator, [](T element, T acc){return element + acc;});
}
static std::vector<T> map(const std::vector<T> &array, const std::function<T(T)> &functor){
std::vector<T> ret;
transform(array.begin(), array.end(), std::back_inserter(ret), functor);
return ret;
}
static std::vector<T> filter(const std::vector<T> &array, const std::function<bool(T)> &functor){
std::vector<T> ret;
copy_if(array.begin(), array.end(), std::back_inserter(ret), functor);
return ret;
}
static bool all(const std::vector<T> &array, const std::function<bool(T)> &functor){
return all_of(array.begin(), array.end(), functor);
}
static bool any(const std::vector<T> &array, const std::function<bool(T)> &functor){
return any_of(array.begin(), array.end(), functor);
}
};
}
//#undef __WH_HPP
I wouldn't inherit nor compose a class with it, since I've never been able to do it peacefully without any side-effects, but I came up with this, just const references.
The problem of course, is the extremely verbose code you have to make in order to use these static methods:
int main()
{
vector<int> numbers = {1,2,3,4,5,6};
numbers = wh::vector<int>::filter(numbers, [](int number){return number < 3;});
numbers = wh::vector<int>::map(numbers,[](int number){return number + 3;});
for(const auto& number: numbers) cout << number << endl;
return 0;
}
If only there was syntactic sugar that could make my static methods have some kind of more common syntax like:
myvector.map([](int number){return number+2;}); //...
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().
I'm trying to create an Enum that has a string label and a value and I plan to use this to read stuff from an ini file.
For example in the ini file I might have some double, int or string type values preceded by the tag/name of the value:
SomeFloat = 0.5
SomeInteger = 5
FileName = ../Data/xor.csv
When I read the tag from a file it comes in as a string, so I'd just like to have std::set that keeps all of my values... when I read the tag I can just compare it against the EnumType and if matches the label then I will check the type and do the proper conversion (atoi or just use the string, etc.)
For example:
EnumType<int> someInteger;
someInteger.label = "SomeInteger";
someInteger.type = INT;
std::set<EnumType> myValues;
//
// populate the set
myValues.insert(someInteger);
//
void ProcessTagAndValue(const std::string &tag, const std::string &value)
{
switch(myValues[tag].type)
{
case INT:
myValues[tag].value = atoi(value);
break;
case DOUBLE:
//
break;
case STRING:
myValues[tag].value = value;
break;
default:
break;
}
}
enum ValueType{INT,DOUBLE,STRING];
template <class T>
struct EnumType{
std::string label;
ValueType type;
T value;
bool operator==(const EnumType &other) const {
return this->label == other.label;
}
bool operator==(const T& other ) const
{
return this->value == other;
}
T& operator=(const T& p)
{
value = p;
return value;
}
EnumType& operator=(const EnumType& p)
{
if (this != &p) { // make sure not same object
this->label = p.label;
this->value = p.value;
}
return *this;
}
};
I have several questions:
Can you guys tell me any better solutions? I'm not sure if I'm trying to be too clever for my own good, or if this is really a viable solution.
If my solution is acceptable, then can anybody tell me how I can declare a set of std::set<EnumType<...>> so that it can accept any type (int, double, string) without me actually knowing which type the enum is going to be using for the value?
If you have any code, then it would be GREAT! :)
If you have limited and very stable set of types, then Boost.Variant may be used.
If you going to add support for new types later, then better forget about this method. In this situation solution, based on Boost.Any, or pair of strings will be better.
typedef boost::variant<int, double, std::string> ValueType;
struct EnumType {
std::string label;
ValueType value;
};
Another question is: "How these values will be used later?" If you are going to pass "SomeInteger" to function, accepting int, you still have to run code similar to:
acceptInt( get<int>( v.value ) ); // get may throw
This approach works better when you have uniform processing of fixed set of types:
class processValue : public boost::static_visitor<>
{
public:
void operator()(int i) const
{
acceptInt( i );
}
void operator()(double d) const
{
acceptDouble( d );
}
void operator()(const std::string & str) const
{
acceptString( str );
}
};
boost::apply_visitor( processValue(), v.value );
Have you looked at Boost.Any? It should do what you want (and if you need to roll your own, you can peek at the source for hints).