I have a class Property containing a data of type Matrix and which overloads operators ->, * and &, Matrix being another class of mine. The overloads give direct access to the data, e.g.
Property myProp;
myProp->trace();
The above code allows to compute the trace of the matrix directly from the Property containing it and without having to first get the data: handy.
Now I want to add a callback to my Property which is called when the Property gets updated. To do so I would like to be able to write something like:
myProp->registerCallback(myCallback);
My problem is that operator-> returns a reference to the Matrix, hence registerCallback gets called on the matrix class, not on Property. As I also overloaded the other operators * and &, it seems I am no longer able to call a member functions from Property.
Hence my question: is there any trick to work with the basic type after an operator was overloaded to return another type?
Thanks a lot!
In C++11 there is std::addressof function. Also boost library provides addressof function.
Example:
#include <iostream>
#include <memory>
struct Data
{
void foo() {
std::cout << "Data::foo" << std::endl;
}
};
template <typename T>
class Property
{
public:
Property() : data(new T) {}
~Property() { delete data; }
T** operator &() {
return &data;
}
T* operator->() {
return data;
}
void foo() {
std::cout << "Property::foo" << std::endl;
}
private:
T *data;
};
int main()
{
Property<Data> p;
p->foo();
std::addressof(p)->foo();
}
You should still be able to call functions in Property with the . operator...
Property myProp;
myProp->trace();
myProp.registerCallback(myCallback);
You've got a minor misunderstanding. If you overload operator* and operator-> then you object is trying to work like a pointer. This situation comes up often with iterators. An iterator's methods are called with . like this.
I have no idea why you would want to overload operator&; to achieve the same thing as fasked's operator&, just use &(*myProp). Besides, &myProp should give you the address of myProp, not its contained object.
Related
I am having trouble calling a function pointer inside a structure. I have used this approach before outside of classes, but now that I am trying it inside a class method using function pointers to other class methods.... I am receiving a compiler error. Here is my class:
class Myclass
{
int i;
void cmd1(int)
{}
void cmd2(int)
{}
void trans()
{
const struct
{
std::string cmd;
void (Myclass::*func)(int)
}
CmdTable[] =
{
{ "command1", &Myclass::cmd1 },
{ "command2", &Myclass::cmd2 }
};
CmdTable[0].func(i);
CmdTable[1].func(i);
}
};
The lines CmdTable[0].func(i); and CmdTable[1].func(i); both provide the following
error:
Error: expression must have (pointer-to-) function type.
I realize there are probably better ways of doing this, but I'm rather curious as to why what I've written doesn't work. Any explanation would be greatly appreciated.
The pointer-to-member-function is a pure class property. You need to combine it with a class instance in order to make a meaningful function call. For example, to use the instance *this, you can use the operator ->* and say:
(this->*CmdTable[0])(i);
Or you can use operator .* on an object value:
(*this.*CmdTable[0])(i);
The latter form is always correct. For the former, note that operator->* may be overloaded and do something unrelated.
I need to store multiple types of a template class in a single vector.
Eg, for:
template <typename T>
class templateClass{
bool someFunction();
};
I need one vector that will store all of:
templateClass<int> t1;
templateClass<char> t2;
templateClass<std::string> t3;
etc
As far as I know this is not possible, if it is could someone say how?
If it isn't possible could someone explain how to make the following work?
As a work around I tried to use a base, non template class and inherit the template class from it.
class templateInterface{
virtual bool someFunction() = 0;
};
template <typename T>
class templateClass : public templateInterface{
bool someFunction();
};
I then created a vector to store the base "templateInterface" class:
std::vector<templateInterface> v;
templateClass<int> t;
v.push_back(t);
This produced the following error:
error: cannot allocate an object of abstract type 'templateInterface'
note: because the following virtual functions are pure within 'templateInterface'
note: virtual bool templateInterface::someFunction()
To fix this error I made the function in templateInterface not a pure virtual by providing a function body, this compiled but when calling the function the overide is not used, but instead the body in the virtual function.
Eg:
class templateInterface{
virtual bool someFunction() {return true;}
};
template <typename T>
class templateClass : public templateInterface{
bool someFunction() {return false;}
};
std::vector<templateInterface> v;
templateClass<int> i;
v.push_back(i);
v[0].someFunction(); //This returns true, and does not use the code in the 'templateClass' function body
Is there any way to fix this so that the overridden function is used, or is there another workaround to store multiple template types in a single vector?
Why your code doesn't work:
Calling a virtual function on a value doesn't use polymorphism. It calls the function which is defined for the type of this exact symbol as seen by the compiler, not the runtime type. When you insert sub types into a vector of the base type, your values will be converted into the base type ("type slicing"), which is not what you want. Calling functions on them will now call the function as defined for the base type, since not it is of that type.
How to fix this?
The same problem can be reproduced with this code snippet:
templateInterface x = templateClass<int>(); // Type slicing takes place!
x.someFunction(); // -> templateInterface::someFunction() is called!
Polymorphism only works on a pointer or reference type. It will then use the runtime type of the object behind the pointer / reference to decide which implementation to call (by using it's vtable).
Converting pointers is totally "safe" with regard to type slicing. Your actual values won't be converted at all and polymorphism will work as expected.
Example, analogous to the code snippet above:
templateInterface *x = new templateClass<int>(); // No type slicing takes place
x->someFunction(); // -> templateClass<int>::someFunction() is called!
delete x; // Don't forget to destroy your objects.
What about vectors?
So you have to adopt these changes in your code. You can simply store pointers to actual types in the vector, instead of storing the values directly.
When working with pointers you also have to care about deleting your allocated objects. For this you can use smart pointers which care about deletion automatically. unique_ptr is one such smart pointer type. It deletes the pointee whenever it goes out of scope ("unique ownership" - the scope being the owner). Assuming the lifetime of your objects is bound to the scope this is what you should use:
std::vector<std::unique_ptr<templateInterface>> v;
templateClass<int> *i = new templateClass<int>(); // create new object
v.push_back(std::unique_ptr<templateInterface>(i)); // put it in the vector
v.emplace_back(new templateClass<int>()); // "direct" alternative
Then, call a virtual function on one of these elements with the following syntax:
v[0]->someFunction();
Make sure you make all functions virtual which should be possible to be overridden by subclasses. Otherwise their overridden version will not be called. But since you already introduced an "interface", I'm sure you are working with abstract functions.
Alternative approaches:
Alternative ways to do what you want is to use a variant type in the vector. There are some implementations of variant types, the Boost.Variant being a very popular one. This approach is especially nice if you don't have a type hierarchy (for example when you store primitive types). You would then use a vector type like std::vector<boost::variant<int, char, bool>>
Polymorphism only works through pointers or references. You'll
need the non-template base. Beyond that, you'll need to decide
where the actual objects in container will live. If they're all
static objects (with sufficient lifetime), just using
a std::vector<TemplateInterface*>, and inserting with
v.push_back(&t1);, etc., should do the trick. Otherwise,
you'll probably want to support cloning, and keep clones in the
vector: preferably with Boost pointer containers, but
std::shared_ptr can be used as well.
The solutions given so far are fine though be aware that in case you were returning the template type other than bool in your example , none of these would help as the vtable slots would not be able to be measured before hand. There are actually limits , from a design point of view , for using a template oriented polymorphic solution.
Solution nr. 1
This solution inspired by Sean Parent's C++ Seasoning talk. I highly recommend to check it out on youtube. My solution simplified a bit and the key is to store object in method itself.
One method only
Create a class that will invoke method of stored object.
struct object {
template <class T>
object(T t)
: someFunction([t = std::move(t)]() { return t.someFunction(); })
{ }
std::function<bool()> someFunction;
};
Then use it like this
std::vector<object> v;
// Add classes that has 'bool someFunction()' method
v.emplace_back(someClass());
v.emplace_back(someOtherClass());
// Test our vector
for (auto& x : v)
std::cout << x.someFunction() << std::endl;
Several methods
For several methods use shared pointer to share object between methods
struct object {
template <class T>
object(T&& t) {
auto ptr = std::make_shared<std::remove_reference_t<T>>(std::forward<T>(t));
someFunction = [ptr]() { return ptr->someFunction(); };
someOtherFunction = [ptr](int x) { ptr->someOtherFunction(x); };
}
std::function<bool()> someFunction;
std::function<void(int)> someOtherFunction;
};
Other types
Primitive types (such as int, float, const char*) or classes (std::string etc.) may be wrapped in the same way as object class do but behave differently. For example:
struct otherType {
template <class T>
otherType(T t)
: someFunction([t = std::move(t)]() {
// Return something different
return true;
})
{ }
std::function<bool()> someFunction;
};
So now it is possible to add types that does not have someFunction method.
v.emplace_back(otherType(17)); // Adding an int
v.emplace_back(otherType("test")); // A string
Solution nr. 2
After some thoughts what we basically done in first solution is created array of callable functions. So why not just do the following instead.
// Example class with method we want to put in array
struct myclass {
void draw() const {
std::cout << "myclass" << std::endl;
}
};
// All other type's behaviour
template <class T>
void draw(const T& x) {
std::cout << typeid(T).name() << ": " << x << std::endl;
}
int main()
{
myclass x;
int y = 17;
std::vector<std::function<void()>> v;
v.emplace_back(std::bind(&myclass::draw, &x));
v.emplace_back(std::bind(draw<int>, y));
for (auto& fn : v)
fn();
}
Conclusion
Solution nr. 1 is definitely an interesting method that does not require inheritance nor virtual functions. And can be used to other stuff where you need to store a template argument to be used later.
Solution nr. 2, on the other hand, is simpler, more flexible and probably a better choice here.
If you're looking at a container to store multiple types, then you should explore boost variant from the popular boost library.
Is it possible to pass different objects as argument for 1 function, not making 3 functions
i.e
void someFunction(Object o) {
//working with object, all that objects have same fields to work with
// i.e. all objects have x, y fields and this function is working with it
}
Player pl;
Item itm;
Block bl;
someFunction(pl);
someFunction(itm);
someFunction(bl);
Maybe it can be done using templates or what?
I dont want to make 3 functions with same code for different objects
Yes, using templates:
template<class Type> void someFunction(const Type& o) {
//working with object, all that objects have same fields to work with
// i.e. all objects have x, y fields and this function is working with it
}
Note that you probably will prefer to pass o by const reference, not by value. I have done this here.
Yes, a template should work:
template <typename T>
void someFunction(T & o)
{
// use o.x, o.y, o.z
}
You can pass by reference or const-reference, depending on whether you want to modify the original object or not.
Templates can be used as an alias for a class of types. The following will allow any type to pass through the parameters of f.
template <typename T> void f(T & t) {
// ...
}
A template should work, but without taking SFINAE into account, you cannot assure that all the given objects have some fields.
Another solution could be inheritance here some sample code:
struct Foo
{
int x;
int y;
};
struct Bar: public Foo
{
int another_x;
};
struct Baz: public Foo
{
int another_y;
};
void someFunction(const Foo &foo)
{
std::cout << foo.x << '\n';
std::cout << foo.y << '\n';
};
With this approach, you can assure that all the given objects have the required members.
You can do this with templates or polymorphism (probably a parent interface with virtual methods to get and set relevant fields).
Templates will work and probably be well optimized, but will not allow new objects to be passed in later, regardless of whether they have the same fields. You will be able to compile new code and new objects to use the template functions, but existing calls will be stuck with a single type.
Using a parent interface and virtual methods, then making your function call those methods (presumably getters and setters) to handle the field manipulation will provide more freedom later, at the expense of slightly higher runtime and having to inherit from that interface (it will, however, allow new objects to be passed to the function at any time, so long as they implement the interface).
I would like to call a function on all elements of a boost::fusion::vector. The elements are of types like this:
class A {
...
void print_with_prefix(const char *prefix) {
std::cout << prefix << *this;
}
};
One can call this function on each element in this way:
// Call print_with_prefix() on a boost::fusion sequence:
struct CallPrintWithPrefix {
const char *prefix_;
CallPrintWithPrefix(const char *prefix) : prefix_(prefix) {}
template <class T> void operator()(T &element) const {
element.print_with_prefix(prefix);
}
}
template <class BoostFusionVector>
void print_all(BoostFusionVector &v, const char *prefix) {
boost::fusion::for_each(v, CallPrintWithPrefix(prefix));
}
However, this implementation of print_all() including helper class is pretty ugly and seems overly complicated! Assuming C++0x is allowed, what is the right way to implement it?
What you did is the right way. C++0x can't help much in that respect because e.g. lambda expressions are not polymorphic, so at the end of the day you'll have to write a template somewhere (which unfortunately must be at namespace scope, even with C++0x), like you did with the operator().
Some libraries like Boost.Phoenix allow to create polymorphic functors on the fly though. For instance ref(std::cout) << arg1 creates an object that is capable of passing any kind of argument to std::cout. It won't help in your case since you're calling a member function.
It's the second time I'm mentioning it today, but I do have a make_overload facility that allows me to create an overloaded functor on the fly. It could help in your case if the set of element types is small and not likely to change. For instance assuming there's only two such types A and B:
auto overload = make_overload(
[prefix](A& a)
{ a.print_with_prefix(prefix); }
, [prefix](B& c)
{ b.print_with_prefix(prefix); } );
boost::fusion::for_each(v, overload);
This is a slightly different question to this one ([Accessing a method from a templated derived class without using virtual functions in c++?) which I asked recently.
I would like to create an instance of an object using a templated factory method, then from then on only be able to set and get a value based on the initial type supplied to the item.
Here's a quick example of what I'm trying to achieve:
boost::shared_ptr<Item> item = Item::create<float>();
item->setValue(5); // conversion to 5.0 in setting the value
float value = item->value(); // returned value = 5.0
Essentially the only time setValue will fail is if there isn't an implicit conversion from whatever has been supplied to the initial 'type' of the internal value in Item.
So if I made the whole Item class a templated class taking a type, I would need to provide the type of the value every time I created a shared pointer to the Item, which I don't really care about.
The next approach I took was to try and store the initial type in the class and use boost::any for the internal storage, casting the internal type to the initial type specified if there was an implicit conversion. However, I stuggled to store and compare the type information, initially looking at std::type_info, but as setValue took a boost::any, had no way of comparing what was actually passed.
(A slight extension to this might be providing a variant-style list of options to the template argument in the creation and returning the value in the native supplied type.)
There may be a design pattern I'm not aware of, or a different approach I haven't considered, so I'd be interested in hearing any suggestions of how to tackle this?
Consider this:
boost::shared_ptr<Item> item1 = Item::create<float>();
boost::shared_ptr<Item> item2 = Item::create<string>();
item1 and item2 have the same (static) type: boost::shared_ptr. So there isn't any way you can make this compile:
item2.setValue("foo");
and have this fail to compile:
item1.setValue("foo");
I'm not sure what you're saying about "if I made the whole Item class a templated class taking a type, I would need to define this every time I call setValue or value (setValue<float>(5))". It sounds like you're actually talking about making each method templated, not the whole class. If the Item class was templated then you'd write:
boost::shared_ptr<Item<float> > item = Item<float>::create();
and then you can easily have the setValue() method accept only the matching type.
Does this work for you?
#include <iostream>
#include <boost/shared_ptr.hpp>
using namespace std;
using namespace boost;
template<typename T> class Item
{
Item(); // prohibited
Item (const T & t) : m_value(t) {}
public :
static shared_ptr<Item<T>> Create(const T & t)
{ return shared_ptr<Item<T>>(new Item<T>(t)); }
const T & getValue() const { return m_value; }
void setValue(const T & v) { m_value = v; }
private :
T m_value;
};
template<typename T> class Factory
{
public :
static shared_ptr<Item<T>> CreateItem(const T & value)
{ return Item<T>::Create(value); }
};
void main()
{
shared_ptr<Item<int>> a = Factory<int>::CreateItem(5);
shared_ptr<Item<float>> b = Factory<float>::CreateItem(6.2f);
std::cout << a->getValue() << std::endl;
std::cout << b->getValue() << std::endl;
a->setValue(3);
b->setValue(10.7f);
std::cout << a->getValue() << std::endl;
std::cout << b->getValue() << std::endl;
}
edit - enforced more const-ness nazism.
Your problem with boost::any is that it's too flexible. The basic idea behind it is still sane. What you need to do is wrap the initial value in an object of type template<typename T> class ItemOfType<T> : public Item. Item::create<T> would then return such a typed object. When you later try to assign a U, you first test if you can dynamic_cast your this to ItemOfType<U>*. This covers your T==U case.
The harder part is the question whether a U is assignable to a T. The usual solution is to instantiate templates, but in your create<T> you don't have the U and in your Item::operator=(U const) you don't have the original T.
This sounds very similar to boost.any. Have you look at this already?