I have to create objects of three-four classes, all inherited from one base class, but some of the objects need to have different behavior - like complete change of one function; I can do this through more inheritance and polymorphism, but it doesn't seem like a good idea.
My first solution was to use specialized templates(for every nonstandard case), but then I have though about lambdas as template parameter(like here: Can we use a lambda-expression as the default value for a function argument? ) and use them instead class method(like here: C++11 lambda and template specialization ) - for me it's much better solution, because I only have to pass lambda for every weird situation:
auto default_lambda = [&]() -> int {return this->Sth;};
template<typename functor = decltype(default_lambda)>
class SomeClass{
...
Problem is with this pointer - method which I want to change need access to non-static methods and lambda is defined outside of non-static method. Moreover, I can't pass reference to class to lambda, because it's a template class(or maybe I'm wrong?).
Of course, I can use specialized template or just function pointers, but I really like solution with lambdas and I consider it much more fine than my other ideas.
Is there any way to "avoid" this problem? Or maybe my idea was bad all along?
There are at least three obvious problems with your approach:
The class SomeClass won't get access to private members, i.e. use of this is out of question.
You attempt to bind this from the context but there is no context i.e. nothing bind to. You will have to pass the object to dealt with a function parameter.
You only specified a type of the function object but no instance, i.e. you won't be able to use it later.
That said, it seems you could just use the type of a custom function object type rather than some lambda function (sure, this is absolutely unsexy but in return it actually works):
struct default_lambda {
template <typename T>
int operator()(T const& o) const { return o.x(); }
};
template <typename F = default_lambda>
class SomeClass {
...
};
If you need complete change of one function, you have two choices:
One virtual function, using perhaps local classes + type erasure if you have many such objects and you don't want to create many namespace scope types:
std::function, which can be rebound later if you wish.
Example code for the first solution (you can even make this a template):
std::unique_ptr<my_base2> get_an_object()
{
class impl : public my_base2
{
void my_virtual_function() { blah blah; }
};
return std::unique_ptr<my_base2>(new impl);
}
Both are generally superior to templates in this situation (but without context it is hard to tell).
Related
I have a class template, and I do not know if I need to have as one of its arguments class Func or not. I also do not know if I can arbitrarily store a std::function directly into a container without its template argument parameter list. My class looks something like:
template<class Data, class Func>
class ThreadManager final {
private:
std::vector<std::shared_ptr<Data>> storedDataPtrs;
std::vector<std::shared_ptr<std::thread>> storedThreadPtrs;
// Is this valid? I know that `std::function is a class template wrapper
// that depends on template argument types. However I do not know
// what kind of func will be stored...
std::vector<std::shared_ptr<std::function>> storedFunctionPtrs;
public:
ThreadManager() = default;
~ThreadManager() = default; // will change to clean up containers.
ThreadManager( const ThreadManager & c ) = delete;
ThreadManager& operator=( const ThreadManager & c ) = delete;
};
Also similar when I go to write the function that will add the data, thread and function object {function object, function pointer, lambda, std::function<...>} Would I be able to declare the parameter for the function similarly?
Or should I just use the actual template argument itself?
std::vector<std::shared_ptr<Func>> storedFuncPtrs;
And if the second case here is the preferred way, then how would I go about to actually store the func obj? Would std::forward or std::move be preferred? Should the method to add in the objects be declared as Func&& func?
I'd like to keep this class as generic, modular and portable as possible while trying to maintain modern c++17 best practices.
Edit
After listening to user Liliscent's advice I think this is what she was stating throughout the comments.
std::vector<std::function<Func>> _storedFuncObjs;
Why is this class storing std::threads and Datas and Funcs?
What Callable are you starting those threads with?
Instances of Func applied to Data?
You only need the threads.
Instances of Func applied to passed arguments, such that a Data is produced?
Store std::future<Data>s (and possibly threads, depending on how you create the futures)
Instances of Func that you will call at some future point?
Store std::packaged_task<Data(Args...)> and hand out the std::future<Data>s those created.
The example below is a minimal, maybe not so good example of a well known idiom.
It compiles and it is so ugly in order to be able to maintain it minimal, because the question is not about the idiom itself.
struct Foo {
virtual void fn() = 0;
};
template<class T>
struct Bar: public Foo {
void fn() override {
T{}.fn();
}
};
struct S {
void fn() { }
};
int main() {
Foo *foo = new Bar<S>{};
foo->fn();
}
What I'm struggling with since an hour ago is how to change it (or even, if there exists an alternative idiom) to introduce a variadic template member method.
Obviously, I cannot modify the fn function of the Foo class, because it's a virtual one and virtual specifier doesn't goes along with templates. The same is valid for the fn specification of Bar, because it has to override somehow the one in the base class.
Note.
For I strongly suspect that this question could be one of the greatest XYProblem ever seen, I'd like also to give a brief description of the actual problem.
I have a class that exposes two templated member methods:
the first one accepts a template class T that is not used immediately, instead it should be stored somehow in order to be used later.
the second one accepts a variadic number of arguments (it is actually a variadic templated member function) and those arguments should be perfectly forwarded to a newly created instance of T.
Well, the problem is far more complex, but this is a good approximation of it and should give you an idea of what's the goal.
Edit
I guess that it is somehow similar to higher order functions.
I mean, what would solve the problem is indeed a templated function to which to bind the first argument, but as far as I know this is impossible as well as any other approach I've explored so far.
Any viable solution that expresses the same concept?
What I mentioned in the comments is the following approach:
template<typename T> class Factory {
public:
template<typename ...Args>
auto construct(Args && ...args)
{
return T(std::forward<Args>(args)...);
}
};
So now, your first exposed class method will be something like this:
template<typename T>
auto getFactory() {
return Factory<T>();
}
So:
auto factory=object.getFactory<someClass>();
// Then later:
factory.construct(std::string("Foo"), bar()); // And so on...
Instead of construct() you could use operator() too, so the second part of this becomes, simply:
factory(std::string("Foo"), bar()); // And so on...
As I mentioned, this is not really type erasure. You can't use type erasure here.
Having given this a few minutes' more thought, the reason that type erasure cannot be used here is because a given instance of type erasure must be "self contained", or atomic, and what you need to do is to break atomic type erasure into two parts, or two class methods, in your case.
That won't work. Type erasure, by definition, takes a type and "erases" it. Once your first function type-erases its class method template parameter, what you end up with is an opaque, type-erased object of some kind. What was type-erased is no longer available, to the outside world. But you still haven't type-erased your constructor parameters, which occurs somewhere else.
You can type-erase the template class, and the constructor parameters together. You can't type-erase the template class, and the constructor parameters, separately and then somehow type-erase the result again.
The simple factory-based approach, like the one I've outlined, would be the closest you can get to results that are similar to type erasure, if both halfs of your desired type-erasure appear in the same scope, so you can actually avoid type-erasure, and instead rely on compiler-generated bloat.
I also agree that you cannot do exactly what you want here. I will post what I think the closest option is (at least a close option that is different from SamVarshavchik's answer).
I don't expect this answer to solve your problem exactly, but hopefully it will give you some ideas.
struct Delay // I have no idea what to call this
{
template <class T>
void SetT()
{
function_ = [](boost::any params){return T(params);}
}
template <class ... Args>
boost::any GetT(Args ... args)
{
return function_(std::make_tuple(args...));
}
private:
std::function<boost::any(boost::any)> function_;
};
The obvious limitation of this is that anyone calling GetT will somehow have to know what T was already, though you can query the boost::any object for the type_info of its class if that helps. The other limitation here is that you have to pass in T's that take a boost::any object and know what to do with it. If you cannot have T do that, then you can change SetT (or create a new member function) like this:
template <class F>
SetTFactory(F f)
{
function_ = f;
}
and then use it like:
Delay d;
d.SetTFactory([](boost::any s){return std::string(boost::any_cast<const char*>(s));});
auto s = d.GetT("Message");
assert(s.type() == typeid(std::string));
This of course introduces a whole new set of difficulties to deal with, so I don't know how viable this solution will be for you. I think regardless of anything else, you're going to have to rethink your design quite a bit.
There is an interesting template presented on Wikipedia for Properties.
This template provides something interesting, in that it allows providing logic around member accesses. Building on this, we could easily build something like this:
struct Ranged {
ranged_property<float,0,1> unit_property;
};
Where the range of unit_property is enforced to be within [0,1].
How can we provide a similar functionality the depends on the hosting class' members? For example:
struct AdjustableRanged {
float max;
ranged_property<float,0,max> influenceable_property;
};
Where the range of influenceable_property is affected by the value of max. Keep in mind, the goal is for this kind of template to be recycled across many vastly different classes. Related concepts are mixins and decorators.
It can be done with macros... but I feel like there must be a better more idiomatic C++ solution.
Edited to add: I think this could be done by saving a reference to the member inside the ranged_property template... but that seems to be a complete waste of space for what would be effectively a constant value; ETA; A const reference may serve the purpose actually, however, I need to do the investigation.
Following up on our discussion in the comments, it seems the functionality can be achieved with a pointer-to-member template parameter like this (but see the caveats below):
#include <iostream>
template<typename C, typename T, T C::*m>
struct PrintMember {
C& obj;
PrintMember(C& obj) : obj(obj) {};
void print() { std::cout << "Member of containing class: " << obj.*m << std::endl; };
};
struct TestClass {
int data;
PrintMember<TestClass, int, &TestClass::data> pm;
TestClass() : pm(*this){};
};
int main()
{
TestClass tc;
tc.data = 5;
tc.pm.print();
}
This only demonstrates that it is possible to access members of the containing object. There are a few things that this approach doesn't solve:
If you really only want to access one member, it's not worth it, since you have to save a reference to *this in the PrintMember member to be able to dereference the pointer to member. So it doesn't actually solve the problem of having to store a reference. You could just as well pass a reference to the member variable itself in the constructor. However, if you need to access multiple members, this allows you to only store one reference (to *this) and still access all of them.
Specifying the template arguments of PrintMember and initializing the PrintMember member variable with *this in the constructor is tedious. Maybe, some clever template argument deduction can help here, but I haven't tried yet and I am not even sure it would get any simpler...
In some special cases, there might be dirty ways to get access to the "this" pointer of the enclosing class without saving it explicitly, like the answer using offsetof in this answer, but my feeling tells me you wanted something portable and less brittle...
I have a class template that is parameterized by a type and a function for extracting a value for that type
template <class T, class getT>
class MyClass{
//holds a vector of T
std::vector<T> Ts;
function useTs(){
f(getT{}(Ts[0]));
}
};
struct TGetter{
someType operator()(const ConcreteT& myT){
return myT.aField;
}
}
struct TGetter2{
someType operator()(const ConcreteT& myT){
return myT.bField;
}
}
MyClass<myT, TGetter> myInstance;
MyClass<myT, TGetter2> myInstance2;
Is there a more elegant way to express this idiom? I don't like having to instantiate the struct every time I want to get at the field in a T. I assume the construction/method call will get optimized out, but it seems like an ugly solution. I wanted to pass a lambda as a template parameter, but I didn't think passing a function value was possible, so I used a struct type instead.
A bit of context: I have a set of physics objects and I have an acceleration structure that I need to construct using a few different state vectors of each object (currentPosition, oldPosition, etc).
As far as I understand your idiom, you are reinventing the std::function , a general-purpose polymorphic function wrapper, and a powerful way to encapsulate a function in C++.
myT foo1;
myT foo2;
std::function<void(myT)> getter1= &myT::TGetter;
getter1(foo1);
getter1(foo2);
std::function<void(myT)> getter2= &myT::TGetter2;
getter2(foo1);
getter2(foo2);
// etc...
The nice thing is that you will be able to encapsulate member and non member functions, lambdas and free functions.
well, there are several options:
1) ugly solution: give a memory offset. and retrieve it from memory. This does not need to be templated.
2) more elegant solution (imo) :
save a function pointer in MyClass like this:
someType (T::*m_fptr)(const T&);
initialize the pointer in the constructor (not as templateparameter), with a getter and setter that is defined in concreteT.
3) template version of 2 is explainer here
Passing a pointer to a member function as a template argument. Why does this work?
I do not understand though what you mean with "function UseTs..." so it might not be the good solution, hope I could help
Instead of using templates, I'd use strategy pattern.
Given a class with a member template function like this one:
template <typename t>
class complex
{
public:
complex(t r, t im);
template<typename u>
complex(const complex<u>&);
private:
//what would be the type of real and imaginary data members here.
}
I am confused about member template functions, please provide an example by which the need of member template functions becomes clear to me.
Also, tell me the use of member template functions in c++, what are the situations where we use member template functions?
It gives you the ability to do conversions:
complex<int> ci;
complex<float> cf(ci);
So, if you have two types T1 and T2 and you can assign a T1 to a T2, this will make it possible to assign a complex<T1> to a complex<T2>.
As for the question in your code (what would be the type of real and imaginary data members here):
template <typename t>
class complex
{
...
private:
t real_part;
t imaginary_part;
};
The most common valuable use for member template functions I come across in my day-to-day is to reduce code complexity by providing one templated function instead of many functions that do essentially the same thing.
For example, suppose you are working on a server that receives half a dozen related messages and saves the incoming data to half a dozen tables in a database. A straightforward implementation would be to implement 6 message handling functions (psudocode):
class MessageProcessor
{
void OnMessage(const char* msg);
void ProcessMessage100(Data100* data);
void ProcessMessage101(Data101* data);
void ProcessMessage102(Data102* data);
void ProcessMessage103(Data103* data);
void ProcessMessage104(Data104* data);
void ProcessMessage105(Data105* data);
};
MessageProcessor::OnMessage(const char* msg)
{
unsigned int * msgType = ((unsigned int*)msg);
switch( *msgType )
{
case 100 :
ProcessMessage100((Data100*),sg);
break;
case 101 :
ProcessMessage101((Data101*),sg);
break;
::
}
}
MessageProcessor::ProcessMessage100(Data100* data)
{
Record100* record = GetRecord100(key);
record->SetValue(xyz);
}
MessageProcessor::ProcessMessage101(Data101* data)
{
Record101* record = GetRecord101(key);
record->SetValue(xyz);
}
: :
There is an opportunity here to generalize the ProcessMessage() functions, since they do essentially the same thing:
class MessageProcessor
{
OnMessage(const char* msg);
template<class Record, class Data> void Process(Data* data);
};
template<class Record, class Data>
void MessageProcessor::Process<Record,Data>(Data* data)
{
Record* record = GetRecord(key);
record->SetValue(xyz);
}
The GetRecord function can also be generalized, yielding a codebase with 2 functions where there used to be 12. This improves the code by virtue of it being simpler with fewer moving parts, simpler to understand and maintain.
The general purpose and functionality of member function templates is in no way different from that of ordinary (non-member) function templates. The only [irrelevant] difference is that member functions have access to the implicit this parameter.
You understand the general purpose of ordinary function templates, do you? Well, in that case you should understand the general purpose of member function templates, because it is exactly the same.
Using the example you provided, the member template function allows you to construct an instance of complex<T> from complex<U>.
As a concrete example of when this might be useful, suppose you had a complex<double> but wanted a complex<float>. Without the constructor the types are unrelated so the regular copy constructor wouldn't work.
Often you would like some member function of your class to operate on a range. By having templated member functions you make it possible to operate on ranges independent of the container that supplies the range without providing an free function.
The same goes for Functors. Often you'd write a functor that operates on some sipecial pair of iterators but soon realize that it is possible to have the Functor operate on any kind of range. So instead of supplying the template parameters through the encapsulating struct you can supply them through the member function operator() and make type deduction possible.
The first examples that come to mind:
In some container constructors (or assign methods) to take input iterators of unknown type.
std::complex to allow operating on different types than the one the std::complex was instantiated from.
In shared_ptr (whether std::tr1:: or boost::) so that you can keep different types of pointers into a shared object instance in the heap (for which the pointer types can be obtained).
In thread (whether std:: in c++0x or boost::) to receive a functor of unknown type that will be called by the thread instance.
In all cases the usage is the same: you have a function that operates on types that are unknown. As AndreyT perfectly states the same that with regular functions.