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.
Related
I am trying to do the following, and I am not even sure if it's possible.
I want a function that takes in an arbitrary function pointer to pass it to a different function (I am aware this is a code smell, good software engineering practices are not what I want to discuss right now).
In other words what I am looking for would look like:
void method1(arbitraty pointer p)
{
method2(p);
}
I am not sure if there is a way to declare arbitrary function pointers (the return value is guaranteed to be void but the parameters are arbitrary, both in number and type)
Use template and use SFINAE to enable it only if the type deduced is a function pointer type:
template <typename T, std::enable_if_t<std::is_function<T>::value, int> = 0>
void method1(T* p)
{
// ...
}
This might be considered over-engineering by some, but you could try the following:
Create an enum of each callback that you are interested in:
enum GlfwCallback {
KeyCallback,
FramebufferSizeCallback,
// etc.
};
Then create a type family that associates each of these with the corresponding function pointer type. Do this by creating a template struct and repeatedly specializing it:
template<GflwCallback callback>
struct GlfwCallbackType {};
template<>
struct GlfwCallbackType<KeyCallback> {
using CallbackType = GLFWkeyfun;
// or
using CallbackType = void(*)(GLFWwindow *, int, int, int, int);
};
template<>
struct GlfwCallbackType<FramebufferSizeCallback> {
using CallbackType = GLFWframebuffersizefun;
};
// etc.
Then you can write
template<GlfwCallback callback>
void method1(GlfwCallbackType<callback>::CallbackType p) {
// do something with p
method2<callback>(p);
};
Also, note that you can add other types and even static functions and data members to your "type family" as needed by your application.
A possibility to do what you want, but in a nice, type-safe fashion, would be the use of functors, i.e. classes that define an overloading for the operator().
Since a functor is a class, you could set the arguments as data memebers, and move the implementation/calling of the functions that you want to pass as arbitrary pointers into the operator() method, where you can have access to all the parameters through the this pointer.
Furthermore, you can define a hierarchy of functors, each one with specialized parameters and implementations, so you can modify the signature of method2 like the following:
method2(BaseFunctor* myfunctor) {
if (myfunctor)
(*myfucntor)();
}
and setup the right type of functor object in the calling context.
Also check out lambdas (c++11), that are basically a shortcut to functors definition.
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.
I'm using xsd to create c++ code from a xml schema file. For a xml type multiple functions are created (for serialization etc).
If the type is called XmlType multiple functions of the following form are created:
XmlType XmlType_(const XmlType& a, const string& b)
string XmlType_(const XmlType& a)
...
This are normal functions and not members of XmlType and they all have the same name.
For XmlType2 the functions would be called XmlType2_.
I would like to write a utility template class for all the different xml types of my xml scheme. The different functions are going to be called insight this class. What I have so far is something like this:
template<typename T>
using TFunc1 = T (*)(const T&, const string&);
template<typename T>
using TFunc2 = string (*)(const T&);
template<typename T, TFunc1<T> func2, TFunc2<T> func2>
class XmlUtil {
...
};
When create an instance of the XmlUtil class if have to do it like this:
XmlUtil<XmlType, XmlType_, XmlType_> util;
This feels a bit redundant and gets worse, when I have to pass more functions as parameters.
I would like to use the util class like this:
XmlUtil<XmlType, XmlType_> util;
or even better like this
XmlUtil<XmlType> util;
The only way I can think of is to somehow use define, but it doesn't feel right.
Is there an other way to do this?
EDIT:
I'm using a define now:
#define TRPL(name) name, name ## _, name ## _
...
XmlUtil<TRPL(XmlType)> util;
I'll edit this, if I find something better (maybe override sets like Yakk suggested in his answer).
This:
XmlUtil<XmlType> util;
is impossible because there is no way to get from XmlType to XmlType_. Their relationship is discarded after the automatic code generator.
However this:
XmlUtil<XmlType_> util;
may be possible. You can deduce the function type of XmlType_ and then use the deduced return type which will be XmlType. I believe there are standard library function for this purpose.
As for the two different overloads, that may be trickier. I do not think that you can pass a function overload set as a template parameter, the resolution is done on the template argument in the context of the template parameter to one function. I don't think there is a way to defer this action without using the preprocessor.
So I would argue that you should use a #define. It is better than nothing.
This looks like a job for override sets.
static struct foo_override_set_type {
template<typename... Args>
auto operator()( Args...&& args ) const
->
decltype( foo( std::forward<Args>(args)... ) )
{ return ( foo( std::forward<Args>(args)... ) ); }
template<typename T>
operator T() { return foo; }
} foo_override_set;
Objects of type foo_override_set_type represent the entire override set of foo. Calling them with operator() does an override set lookup on foo and calls the resulting function. Casting them to a function pointer does the same thing as casting the token foo to a function pointer (or other value).
Your code generation can auto-generate such override set types. It can also make a traits class that maps from your type XmlType to the override set of XmlType_ functions via specialization.
Then, your XmlUtil<XmlType> can access the override set of XmlType_ via that traits class. It first instantiates the override set variable, then invokes () on it.
As an aside, #Xeo has a proposal to make creating such objects as easy as typing []XmlType_ in C++1y or C++1z.
Default template arguments in the class definition?
Like
template<typename T, TFunc1<T> func1 = XmlType_, TFunc2<T> func2 = XmlType_>
class XmlUtil {
// ...
};
You can use a trait class like this
template <typename T>
struct Trait{
typedef T type;
typedef T (*func1)(const T&, const string&);
typedef string (*func2)(const T&);
};
and make the class XmlUtil have one template parameter (let's name it Trait) and use Trait::type, Trait::func1 and Trait::func2. See here for full usage.
In the example, the type of XmlUtil goes like:
XmlUtil<Trait<XmlType> >
I've done it this way since I don't know well your problem. It might be the case that you can just define the Trait class right into XmlUtil and use
XmlUtil<XmlType>
Other variations are possible, it just depend on what you need.
You can read a very brief introduction to trait classes here. If you want to read more about this topic I suggest you Modern C++ (Alexandrescu).
I am not sure I fully understand what you are asking. The common approach for serialization and deserialization would be to create a factory (abstract factory) and resolve the construction of the objects dynamically. Note that this can be improved for complex structures, where the code generator can create member functions to extract the exact type of each one of the members.
But again, I don't fully understand what you are really trying to do... As a recommendation I believe it would help if you provided more of a description of the problem to solve, as the question focuses on how to make your solution work, and that implicitly discards other approaches that might be better designs.
I need to establish a hash table using a hasher different from the default one, so I write something like:
class foo {
public:
...
private:
struct myhasher {
size_t operator() (myclass bar) { return hash_calculation bar; }
}
static size_t hash_calculation (myclass bar) {
// do some calculation
}
hash_map<myclass, myhasher> myhashmap;
}
It works. Now for some reason I have to write a non-static member function to replace hash_calculation, say, it needs a non-static member of the class as an argument. Then the whole thing failed because I cannot use a non-static method in a nested struct.
This is somehow similar to another widely discussed problem: how to use a non-static function to do comparison or sorting. See for example:
Using a non-static class member inside a comparison function
and
C++ std list sort with custom comparator that depends on an member variable for the object instance . They both established a functor instead of a function as the comparator. However in my case this trick does not work because I need a class name inside the hash_map definition, not a specific struct object. What should I do? Thanks in advance for your help!
You can't. How is the hash_map supposed to know which instance of myhasher should be used when calling myhaser::hash_calculation?
hash_map isn't part of the standard C++ library, not even in C++11, so it's a custom class, and you have included no information about how it works. If there is a way for it to take some sort of constructor argument for which myhasher it should use, you're in luck. But it doesn't sound like it.
Also, you're using pass by value when you probably mean to pass in a const reference. Passing by value is likely going to be really slow and inefficient.
The standard "hash-map", i.e., std::unordered_map<K, V, H, E, A> takes a hash object of type H as constructor argument. A copy of this object is used to determine the hash for the object by way of the function call operator. This way can provide some context. Obviously, you were already using a non-static function call operator but you choose to delegate to a static member.
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).