Suppose I have a list of type list<boost::any> that has some type in it that is unknown. Now suppose I want to apply some operation to the elements in the list that is polymorphic. In this case, consider the + operator. Suppose that I know that the list will always contain a homogenous set of objects that support operator+, and I want to get the result of applying operator+ (the "sum" in one sense) between each element of the list into a new boost::any. Something like this:
boost::any sum(list<boost::any> lst) {
// return lst[0]+lst[1]+lst[2] etc
}
Without enumerating all possible types that could support operator+, is there a way to do this? I'm extremely open to crazy ideas.
(I really do have an ok reason for doing this... I'm implementing an interpreter)
You could use boost::variant instead if you know the range of possible types in the list.
I don't see how you can do this without a mesh of operator+ functions to handle every possible combination of contained types, or regular runtime polymorphism.
What is the concrete type you wish to see in the final boost::any output, I wonder?
btw if you are implementing an interpreter, check out Boost.Spirit which might illuminate your design problem here.
C++ matches functions (and operators are merely fancy functions that have an additional infix syntax) by their types, not by their names, at compile-time. (Rather than checking at run-time whether the objects involved support the requested operation.)
The only exception to that I can think of is virtual functions. If the types were polymorphic, you could use any of the workarounds for missing multi-methods (double dispatch). But since they can be anything, I don't think you can do this.
If you have a limited set of types, template-meta programming might help the generate functions implementing addition. But if the number of types involved were limited, you'd probably use boost::variant.
(IME saying this means that, in very short time, someone comes along and proves me wrong.)
No. Not with boost::any nor with boost::variant (doesn't qualify your, "Without enumerating all possible types that could support operator+," requirement).
What you need to do is make your own. The concept behind boost::any is quite simple. If you look at the documentation they have a link to an article explaining the technique (it's basically the handle/body idiom with polymorphism). All you need to do is decide what interface your various objects must have and write the 'any' interface and it's impl accordingly. Something resembling something like so:
struct my_any
{
template < typename T >
my_any(T const& t) : pimpl(new impl<T>(t)) {}
...
some_type get_some_type() const;
...
private:
struct impl_base
{
....
virtual some_type get_some_type() const = 0;
};
template < typename T >
struct impl : impl_base
{
some_type get_some_type() const { return t.get_some_type(); }
impl(T const& t_var) : t(t_var) {}
....
};
boost::scoped_ptr<impl_base> pimpl;
};
some_type operator+ (my_any const& a, my_any const& b)
{
return a.get_some_type() + b.get_some_type();
}
It's hard to imagine what operator+ would do on generic types so I made something up that makes a small amount of sense to me. You'll of course need to change to your needs.
Related
I am trying to implement a C++ class which will wrap a value (among other things). This value may be one of a number of types (string, memory buffer, number, vector).
The easy way to implement this would be to do something like this
class A {
Type type;
// Only one of these will be valid data; which one will be indicated by `type` (an enum)
std::wstring wData{};
long dwData{};
MemoryBuffer lpData{};
std::vector<std::wstring> vData{};
};
This feels inelegant and like it wastes memory.
I also tried implementing this as a union, but it came with significant development overhead (defining custom destructors/move constructors/copy constructors), and even with all of those, there were still some errors I encountered.
I've also considered making A a base class and making a derived class for each possible value it can hold. This also feels like it isn't a great way to solve the problem.
My last approach would be to make each member an std::optional, but this still adds some overhead.
Which approach would be the best? Or is there another design that works better than any of these?
Use std::variant. It is typesafe, tested and exactly the right thing for a finite number of possible types.
It also gets rid of the type enum.
class A {
std::variant<std::wstring, long, MemoryBuffer, std::vector<std::wstring>> m_data{}; // default initializes the wstring.
public
template<class T>
void set_data(T&& data) {
m_data = std::forward<T>(data);
}
int get_index() { // returns index of type.
m_data.index();
}
long& get_ldata() {
return std::get<long>(m_data); // throws if long is not the active type
}
// and the others, or
template<class T>
T& get_data() { // by type
return std::get<T>(m_data);
}
template<int N>
auto get_data() { // by index
return std::get<N>(m_data);
}
};
// using:
A a;
a.index() == 0; // true
a.set_data(42);
a.index() == 1; // true
auto l = a.get<long>(); // l is now of type long, has value 42
a.get<long>() = 1;
l = a.get<1>();
PS: This example does not even include the coolest (in my opinion) feature of std::variant: std::visit I am not sure what you want to do with your class, so I cannot create a meaningful example. If you let me know, I will think about it.
You basically want QVariant without the rest of Qt, then :)?
As others have mentioned, you could use std::variant and put using MyVariant = std::variant<t1, t2, ...> in some common header, and then use it everywhere it's called for. This isn't as inelegant as you may think - the specific types to be passed around are only provided in one place. It is the only way to do it without building a metatype machinery that can encapsulate operations on any type of an object.
That's where boost::any comes in: it does precisely that. It wraps concepts, and thus supports any object that implements these concepts. What concepts are required depends on you, but in general you'd want to choose enough of them to make the type usable and useful, yet not too many so as to exclude some types prematurely. It's probably the way to go, you'd have: using MyVariant = any<construct, _a>; then (where construct is a contract list, an example of which is as an example in the documentation, and _a is a type placeholder from boost::type_erasure.
The fundamental difference between std::variant and boost::any is that variant is parametrized on concrete types, whereas any is parametrized on contracts that the types are bound to. Then, any will happily store an arbitrary type that fulfills all of those contracts. The "central location" where you define an alias for the variant type will constantly grow with variant, as you need to encapsulate more type. With any, the central location will be mostly static, and would change rarely, since changing the contract requirements is likely to require fixes/adaptations to the carried types as well as points of use.
I have a templated class Foo that can do identity comparisons (via ==), but has a function Foo::sameStructureAs(Foo const & other) for more of a "value" vs. "pointer" notion of equality.
I'd like to make an unordered_map which overrides the hash function and the equality predicate. They default to std::equal_to<Key> and std::hash<Key>...which I provide for my type, based on identity. But I need them to be comparing on the basis of my sameStructureAs.
Since Foo is a template, I do something like this:
template <class> struct same_structure_as;
template <class> struct hash_structure;
template <class T>
struct hash_structure<Foo<T>>
{
size_t operator() (Foo<T> const & value) const
{
// whatever...
}
};
template <class T>
struct same_structure_as<Foo<T>>
{
bool operator() (Foo<T> const & left, Foo<T> const & right) const
{
// whatever...
}
};
Which seems like I'm following roughly the strategy of the classes in std:: for this purpose, and creating something general. So does that look right?
Secondly: Is there any precedent for the naming of this or a prototype already existing in std::? I've thought about words like isomorphic or congruent. It seems like something that would come up often in designing classes when you have more than one idea of what it means to be "equal".
If you are looking at a type through this "different" notion of comparison or equality, ask if what you really need is another type. Perhaps there is some kind of cast or coercion you would apply to the underlying data so that its new notion of equality/assignment/comparison fits this test you are designing.
That way you can properly implement the std:: functions for that type... and use it in collections without having to pass in these extra predicates. So perhaps call the type with pointer-equality semantics FooRef and the one with value semantics Foo.
If for some reason you can't do this...then looking at the names one wants to parallel:
std::equal_to<Key>
std::hash<Key>
Keeping the equal_to and hash in there is probably the closest to "standard" one will accomplish. So rather than introducing new terms like congruence or isometric,call out exactly what is equal or getting hashed...and use the above as suffixes:
std::content_equal_to<Key>
std::content_hash<Key>
If it's the "structure" of something being compared you can apply that with structure_equal_to and structure_hash. Only caveat being that "struct"/"structure" has meaning in C++, so it may lead a reader to think it's comparing type_info or something like that.
I am wrapping a library which I did not write to make it more user friendly. There are a huge number of functions which are very basic so it's not ideal to have to wrap all of these when all that is really required is type conversion of the results.
A contrived example:
Say the library has a class QueryService, it has among others this method:
WeirdInt getId() const;
I'd like a standard int in my interface however, I can get an int out of WeirdInt no problem as I know how to do this. In this case lets say that WeirdInt has:
int getValue() const;
This is a very simple example, often the type conversion is more complicated and not always just a call to getValue().
There are literally hundreds of function calls that return types likes these and more are added all the time, so I'd like to try and reduce the burden on myself having to constantly add a bajillion methods every time the library does just to turn WeirdType into type.
I want to end up with a QueryServiceWrapper which has all the same functionality as QueryService, but where I've converted the types. Am I going to have to write an identically names method to wrap every method in QueryService? Or is there some magic I'm missing? There is a bit more to it as well, but not relevant to this question.
Thanks
The first approach I'd think is by trying with templates such that
you provide a standard implementation for all the wrapper types which have a trivial getValue() method
you specialize the template for all the others
Something like:
class WeirdInt
{
int v;
public:
WeirdInt(int v) : v(v) { }
int getValue() { return v; }
};
class ComplexInt
{
int v;
public:
ComplexInt(int v) : v(v) { }
int getValue() { return v; }
};
template<typename A, typename B>
A wrap(B type)
{
return type.getValue();
}
template<>
int wrap(ComplexInt type)
{
int v = type.getValue();
return v*2;
};
int x = wrap<int, WeirdInt>(WeirdInt(5));
int y = wrap<int, ComplexInt>(ComplexInt(10));
If the wrapper methods for QueryService have a simple pattern, you could also think of generating QueryServiceWrapper with some perl or python script, using some heuristics. Then you need to define some input parameters at most.
Even defining some macros would help in writing this wrapper class.
Briefly, If your aim is to encapsulate the functionality completely so that WeirdInt and QueryService are not exposed to the 'client' code such that you don't need to include any headers which declare them in the client code, then I doubt the approach you take will be able to benefit from any magic.
When I've done this before, my first step has been to use the pimpl idiom so that your header contains no implementation details as follows:
QueryServiceWrapper.h
class QueryServiceWrapperImpl;
class QueryServiceWrapper
{
public:
QueryServiceWrapper();
virtual ~QueryServiceWrapper();
int getId();
private:
QueryServiceWrapperImpl impl_;
};
and then in the definition, you can put the implementation details, safe in the knowledge that it will not leach out to any downstream code:
QueryServiceWrapper.cpp
struct QueryServiceWrapperImpl
{
public:
QueryService svc_;
};
// ...
int QueryServiceWrapper::getValue()
{
return impl_->svc_.getId().getValue();
}
Without knowing what different methods need to be employed to do the conversion, it's difficult add too much more here, but you could certainly use template functions to do conversion of the most popular types.
The downside here is that you'd have to implement everything yourself. This could be a double edged sword as it's then possible to implement only that functionality that you really need. There's generally no point in wrapping functionality that is never used.
I don't know of a 'silver bullet' that will implement the functions - or even empty wrappers on the functions. I've normally done this by a combination of shell scripts to either create the empty classes that I want or taking a copy of the header and using text manipulation using sed or Perl to change original types to the new types for the wrapper class.
It's tempting in these cases to use public inheritance to enable access to the base functions while allowing functions to be overridden. However, this is not applicable in your case as you want to change return types (not sufficient for an overload) and (presumably) you want to prevent exposure of the original Weird types.
The way forward here has to be to use aggregation although in such as case there is no way you can easily avoid re-implementing (some of) the interfaces unless you are prepared to automate the creation of the class (using code generation) to some extent.
more complex approach is to introduce a required number of facade classes over original QueryService, each of which has a limited set of functions for one particular query or query-type. I don't know that your particular QueryService do, so here is an imaginary example:
suppose the original class have a lot of weired methods worked with strange types
struct OriginQueryService
{
WeirdType1 query_for_smth(...);
WeirdType1 smth_related(...);
WeirdType2 another_query(...);
void smth_related_to_another_query(...);
// and so on (a lot of other function-members)
};
then you may write some facade classes like this:
struct QueryFacade
{
OriginQueryService& m_instance;
QueryFacade(OriginQueryService* qs) : m_instance(*qs) {}
// Wrap original query_for_smth(), possible w/ changed type of
// parameters (if you'd like to convert 'em from C++ native types to
// some WeirdTypeX)...
DesiredType1 query_for_smth(...);
// more wrappers related to this particular query/task
DesiredType1 smth_related(...);
};
struct AnotherQueryFacade
{
OriginQueryService& m_instance;
AnotherQueryFacade(OriginQueryService* qs) : m_instance(*qs) {}
DesiredType2 another_query(...);
void smth_related_to_another_query(...);
};
every method delegate call to m_instance and decorated w/ input/output types conversion in a way you want it. Types conversion can be implemented as #Jack describe in his post. Or you can provide a set of free functions in your namespace (like Desired fromWeird(const Weired&); and Weired toWeired(const Desired&);) which would be choosen by ADL, so if some new type arise, all that you have to do is to provide overloads for this 2 functions... such approach work quite well in boost::serialization.
Also you may provide a generic (template) version for that functions, which would call getValue() for example, in case if lot of your Weired types has such member.
There are many reasons not to use typeid. Other than for using members of type_info (implementation defined behavior), it is usually (always?) possible to provide similar functionality using other C++ language features, eg: overloading, virtual functions etc.
So, excluding usage that relies on the implementation defined behavior, does anybody have a real world example where typeid is the best solution?
So, excluding usage that relies on the implementation defined behavior, does anybody have a real world example where typeid is the best solution?
I sometimes use it in debug outputs, to verify that a template argument passed to my function is indeed of a given type. This makes sense in my case since the actual template argument passed to my function is generated by a specialised metafunction and I want to make sure that the right metafunction is used.
boost::any uses typeid to implement any_cast.
template<typename T> any_cast(const any& other) {
if(typeid(T) != other.type()) throw bad_any_cast();
//...actual cast here...
}
You can't be sure T is polymorphic, so dynamic_cast is out of the question, and the enclosed type within the boost::any call is lost by now, so none of the other casts can provide any sort of type safety.
When implementing multimethods (or multiple dispatch), where the actual call is chosen from e.g. a map, using std::type_info* as a key.
Write a dynamic tree where you can on the runtime modify structure of the tree where there are different types in each link, it'll need typeid. dynamic_cast is not enough.
Edit: Here's some details:
class I {
public:
virtual std::string type() const=0;
virtual void *value() const=0;
};
template<class T>
class Impl : public I
{
public:
Impl(T t) : t(t) { }
std::string type() const { return typeid(T).name(); }
void *value() const { return &t; }
private:
T t;
};
And then build a tree out of these:
template<class Node, class Link>
class Tree { };
With link type being the I* interface... Since the above works for any values of type T1,T2,T3,T4, we could also with similar classes for any functions T->T1, T->T2, T->T3, T->T4, and use that function type as the Node of the tree. Now you have proper expressions described in dynamic tree.
You can use typeid to compare the actual types of two objects. Could be useful if you want to check equality of two objects, and first make sure they are of the exact same type (though I must say I haven't seen this done a lot, so there might be a good reason why this is not a good idea...).
I use it to probe the class type of the exception in my catch all handler.
// fudge vtable existence (thrown exceptions must have one)
class StubException
{
virtual ~StubException();
};
.....
catch(...)
{
StubException *e = getExceptionObject(); // compiler/rt specific
std::string s = typeid(e).name();
...
throw;
}
The function getExceptionObject() is part of a small utility library I wrong to access additional information about exceptions. It comes in very handy when a function throws an exception I should be catch but don't. It has definitely saved a lot of frustration over the years since I immediately know the type of exception that needs coverage.
Consider the following piece of code:
class B {
private:
// some data members
public:
friend bool operator==(const B&,const B&);
friend ostream& operator<<(ostream&,const B&);
// some other methods
};
template <typename T=B>
class A {
private:
// some data members
vector<vector<T> > vvlist;
public:
// some other methods
};
My requirement is that the type T that is passed as type parameter must provide definitions for the operator== and the operator<< methods. I do not want to enforce any other restrictions on T.
How can I do this?
One way that I can think of is to Create an Abstract class say "Z" that declares these two methods.
and then write
vector<vector<Z> > vvlist;
and NOT have class A as a template.
Is there a better way to do this?
It happens automatically.
If your code calls the operators == and <<, then the code simply won't compile if the class is passed a type that doesn't define these operators.
It is essentially duck-typing. If it looks like a duck, and quacks like a duck, then it is a duck. It doesn't matter whether it implements an IDuck interface, as long as it exposes the functionality you try to use.
It seems like you are looking for a concept check library. See what Boost has to offer: Boost Concept Check Library. That link also has a good explanation what concepts are. Quote:
A concept is a set of requirements
(valid expressions, associated types,
semantic invariants, complexity
guarantees, etc.) that a type must
fulfill to be correctly used as
arguments in a call to a generic
algorithm
In your question, the concept is "type T must provide operator== and operator<<".
You can write a private method in A that would test required stuff on T in compile time.
void TestReq(T x, T y)
{
if (x==y)
cout << x;
}
This way even plain integers would pass and work.