I was trying to built atop the thread here: Variable length template arguments list?
to have a default Functor class, this is only of academic interest. My goal is to build a generic Fucntor class: given a class name, method name and argument types(of variable length), it builds a class that has an operator() method which takes variable number of arguments of type specified in template args and takes a pointer and applies the given method. Imagine a class thus:
class MyClass
{
public:
float Fraction( float n, int m)
{
return n/m;
}
int Increment(int n)
{
return n+1;
}
} ;
And a templatized functor class that can be used in any function thus:
int k = FunctorClass<MyClass, Increment, int, int /*return type*/> (3);
assert(k == 4);
float l = FunctorClass<MyClass, Fraction, float, int, float, /*return type*/> (4,3);
assert(l == (4/3));
Can such a functor class be constructed?
Sidenote: Cant use Variadic templates, (building in VS2010, no ... template arguments)
Thanks for the help
This is certainly doable, e.g. Boost bind() uses this approach under the hood. Without variadics you won't get full generality, however, because you will be limited to a fixed number of template arguments and you need to type the implementation for each different number of arguments you want to support. Also, without rvalue references you won't get perfect forwarding.
That said, the way you are trying to use it won't work: when stating the member functions, you can't just name them. You need to obtain the correct member function point using e.g. &MyClass::Increment and &MyClass::Fraction. If the member function is overloaded, you need to disambiguate it.
Since you apparently want to enable the use of this function object for non-static member functions, you also need to provide an object on which the member function is to be called. The most reasonable approach for this is to pass a reference to the object as a constructor argument of the function object class and to store it to be used whenever the function is being called. That is, the use looks somewhat different but it can be simplified with some sort of factory function. Here is a version which adjusts the various things and implements a corresponding function object template:
#include <cassert>
// -----------------------------------------------------------------------------
template <typename T, T> class FunctorClass;
template <typename RC, typename Class,
RC (Class::*Member)()>
class FunctorClass<RC (Class::*)(), Member>
{
public:
FunctorClass(Class& object): object_(&object) {}
RC operator()() const { return (this->object_->*Member)(); }
private:
Class* object_;
};
template <typename RC, typename Class, typename A0,
RC (Class::*Member)(A0)>
class FunctorClass<RC (Class::*)(A0), Member>
{
public:
FunctorClass(Class& object): object_(&object) {}
RC operator()(A0 a0) const { return (this->object_->*Member)(a0); }
private:
Class* object_;
};
template <typename RC, typename Class, typename A0, typename A1,
RC (Class::*Member)(A0, A1)>
class FunctorClass<RC (Class::*)(A0, A1), Member>
{
public:
FunctorClass(Class& object): object_(&object) {}
RC operator()(A0 a0, A1 a1) const { return (this->object_->*Member)(a0, a1); }
private:
Class* object_;
};
// -----------------------------------------------------------------------------
class MyClass
{
public:
int foo() { return 17; }
float Fraction( float n, int m)
{
return n/m;
}
int Increment(int n)
{
return n+1;
}
};
int main()
{
MyClass object;
int i = FunctorClass<int (MyClass::*)(), &MyClass::foo>(object)();
assert(i == 17);
int k = FunctorClass<int (MyClass::*)(int), &MyClass::Increment>(object)(3);
assert(k == 4);
float l = FunctorClass<float (MyClass::*)(float, int), &MyClass::Fraction>(object)(4,3);
assert(l == (4.0f/3));
}
I'm not sure you would need variadics to pull this off. Consider the following interface...
template < typename RETURN_TYPE >
class iFunctor abstract {
public:
virtual RETURN_TYPE operator () ( void ) = 0;
};
Abstract interfaces are not full-blown classes, they can contain a partial implementation such as function signatures and some data members. With the template, you can generalized a return type. But what about the argument list you say?
Note how there is no constructor in the interface. In your concrete class (or derived classes) you can pass the burden of variable argument lists to the constructor, like so...
template < typename TYPE >
class ConcreteFunctor_add : public iFunctor < TYPE > {
private:
int A;
int B;
public:
explicit ConcreteFunctor_add ( const int &a, const int &b ) : A(a), B(b) {};
TYPE operator () ( void ) { return ( A + B ); };
};
You deal with the argument list on a case by case basis through the constructor.
The explicit constructor requires an argument list upon declaration, so you'll get your variable list here. So in practice...
ConcreteFunctor_add < int > addInteger ( 10, 10 );
addInteger();
...and you'd be cool.
Related
I want to create a system of "Mapper", i.e objects that takes an input (template) value and return a output (template) value. A mapper can have additional features / traits.
Sample code :
// a trait
template <typename I, typename O>
class Writable
{
public:
virtual ~Writable() = default;
virtual O & operator()(I i) = 0;
};
// another trait
template <typename I, typename O>
class Bounded
{
public:
virtual ~Bounded() = default;
virtual O min() const = 0;
virtual O max() const = 0;
};
// base class
template <typename I, typename O, template<typename, typename> class ... Traits>
class IMap
: public Traits<I, O>...
{
public:
virtual ~IMap() = default;
virtual O operator()(I i) const = 0;
};
// a test mapper
class Test1
: public IMap<int, double, Writable, Bounded>
{
public:
double operator()(int i) const override { return _d; }
double & operator()(int i) override { return _d; }
double min() const override { return 0; }
double max() const override { return 1; }
private:
double _d;
};
// another test mapper
class Test2
: public IMap<int, double, Bounded, Writable>
{
public:
double operator()(int i) const override { return _d; }
double & operator()(int i) override { return _d; }
double min() const override { return 0; }
double max() const override { return 1; }
private:
double _d;
};
// a class to use mappers
template <typename I, typename O>
class MapUse
{
public:
// I would like this function to accept an IMap containing "at least" the Bounded trait
// Ideally this function signature should be like
void method_requiring_writable(IMap<I, O, Bounded> & map)
{
map(123)
map(123) = 0;
}
// I would like this function to accept an IMap containing "at least" the Bounded and Writable traits
// (no matter the actual order of those traits in variadic template parameter )
// Ideally this function signature should be like
void method_requiring_bounded_and_writable(IMap<I, O, Bounded, Writable> & map)
{
map(123);
map(123) = 0;
map.min();
}
};
void test()
{
Test1 t1;
Test2 t2;
Test2 * p = dynamic_cast<Test2*>(&t1); // << always return nullptr, of course !
MapUse<int, double> mu;
mu.method_requiring_writable(t1); // << does not compile, not the right type
mu.method_requiring_bounded_and_writable(t1); // << does not compile, not the right type
return;
}
Error at line : mu.method_requiring_writable(t1) :
error C2664: 'void MapUse<int,double>::method_requiring_writable(IMap<I,O,Bounded> &)': cannot convert argument 1 from 'Test1' to 'IMap<I,O,Bounded> &'
> with
> [
> I=int,
> O=double
> ]
Error at line : mu.method_requiring_bounded_and_writable(t1) :
error C2664: 'void MapUse<int,double>::method_requiring_bounded_and_writable(IMap<int,double,Bounded,Writable> &)': cannot convert argument 1 from 'Test1' to 'IMap<int,double,Bounded,Writable> &'
I perfectly understand why this does not work, but I would like a "trick" to make it work !
First problem : Order of traits in variadic template parameter does count. It should easily be solved by forcing the developer to respect traits order, but it's not ideal
Second problem : Be able to create methods that requires a mapped with "at least" a specific set of traits. No clue about this one.
First approach was not variadic, but a - very - complex hierarchy with lots of virtual heritage --> ugly as hell, it's a real pain to add a new trait
With the code above, I thought about adding some kind of cast operators in IMap but failed to do so.
Any C++ / variadic / magic stuff specialist to help on this ?
You can use something like this:
#include <type_traits>
template <template <class, class> class... Traits,
std::enable_if_t<
std::is_base_of<Bounded<I, O>, IMap<I, O, Traits...>>::value
and std::is_base_of<Writable<I, O>, IMap<I, O, Traits...>>::value
, int> = 0>
void method_requiring_bounded_and_writable(IMap<I, O, Traits...> & map) {
// Do stuff
}
Why do you wan't to check the mixed-in types in the first place? You are mixing generic and non-generic programming here. Simply use the implemented traits (like min() and max()) and forget about how they were implemented. A straight-forward and clean solution is to simply continue using generic programming:
//template <typename I, typename O>
class MapUse {
public:
template <typename T>
void method_requiring_writable(T& map) {
map(123);
map(123) = 0;
}
template <typename T>
void method_requiring_bounded_and_writable(T& map) {
map(123);
map(123) = 0;
map.min();
}
};
Other solutions require heavy meta-programming and only make your code more complex and hard to read. I understand that this might not solve your very specific problem. This is an advise to rethink your design and fully jump on the generic train or drop it altogether.
If I understand correctly, the object ’A’ defined thus:
typedef struct {
int n;
float *p;
} myStruct;
myStruct A;
is an aggregate with exactly the same layout in memory as the object ‘B’ defined as:
template <typename T> class myTemplateClass
{
public:
int n;
T* p;
};
myTemplateClass<float> B;
So, is there a more elegant way of assigning
A = B;
than having to write
A = *(reinterpret_cast< myStruct *>(&B));
every time?
My reason for asking is that I have to call a library function which exposes an interface with arguments of the form ‘myStruct’, from code where holding my data in the form of myTemplateClass is a great deal more natural.
This requires a bit of boilerplate. Two functions per myStruct, and two functions per template.
In the namespace of myStruct inject these two functions:
auto members( myStruct& s ) {
return std::tie(s.n, s.p);
}
auto members( myStruct const& s ) {
return std::tie(s.n, s.p);
}
in C++11 you have to add a decltype clause to give the return value explicitly. Basically tie the members in the exact order declared.
In the body of the myTemplateClass, declare a friend function members that does something similar:
template <typename T>
class myTemplateClass {
public:
int n;
T* p;
friend auto members( myTemplateClass<T>& self ) {
return std::tie( self.n, self.p );
}
friend auto members( myTemplateClass<T> const& self ) {
return std::tie( self.n, self.p );
}
};
finally, write assign:
template<class Lhs, class Rhs>
void assign_by_members( Lhs& lhs, Rhs const& rhs ) {
members(lhs) = members(rhs);
}
and we are done.
Anyone that declares a free function members that returns something assignable to the other members works. tie does element-wise assign on references, so all is good.
Note that only the one being assigned from needs the const& overload of members and only the one being assigned to needs the & overload of members. So if assignment always goes from template class to C-struct, you can halve that boilerplate.
If you don't like the assign_by_members syntax, you can override operator O as follows:
template <typename T>
class myTemplateClass {
public:
// ... see above for code that goes here
template<class O,class=decltype(members(std::declval<O>())>
operator O() const {
O retval;
assign_by_members( retval, *this );
return retval;
}
};
which also does a test to determine if the type converted to supports members. You could go a step further and test if the members return value can be assigned to from the return value of members(*this), but that adds more boilerplate.
You could make myTemplateClass<T> derive from the correct myStruct depending on the type parameter. You can use template specialization for this:
template <typename T> class myTemplateClass;
// Specialization for float
template <> class myTemplateClass<float> : public myStruct {};
// Specialization for int
template <> class myTemplateClass<int> : public myOtherStruct {};
// And so on for other types...
This way, you can assign instances of myTemplateClass<float> to myStruct, and myTemplateClass<int> to myOtherStruct. (Bonus: You don't have to rely on the "same memory layout" guess.)
If you derive from mystruct, then, u can use a static_cast on it.
As suggested above, template specialization would work too.
I would take static_cast over reinterpret_cast any day.
Below is the working code.
typedef struct {
int n;
float *p;
} myStruct;
myStruct A;
template <typename T> class myTemplateClass:public myStruct
{
public:
int n;
T* p;
};
//myTemplateClass<float> B;
typedef myTemplateClass<float> temp;
temp B;
int main()
{
A = *(static_cast< myStruct *>(&B));
My example below suggests that implicit conversions from non-template types to template types won't work as seamlessly as those only involving non-template types. Is there a way to make them work nonetheless?
Example:
struct point;
template<unsigned d> struct vec {
vec() { }
// ...
};
template<> struct vec<2> {
vec() { }
vec(const point& p) { /* ... */ } // Conversion constructor
// ...
};
struct point {
operator vec<2>() { return vec<2>(/* ... */); } // Conversion operator
};
template<unsigned d> vec<d> foo(vec<d> a, vec<d> b) {
return vec<d>(/* ... */);
}
template<unsigned d1, unsigned d2>
vec<d1 + d2> bar(vec<d1> a, vec<d2> b) {
return vec<d1 + d2>(/* ... */);
}
int main(int argc, char** argv) {
point p1, p2;
vec<2> v2;
vec<3> v3;
foo(v2, p1);
foo(p2, v2);
foo(p1, p2);
bar(v3, p1);
}
Is there a way to let this code auto-convert from point to vec<2>?
I know I can overload foo and bar to allow for point arguments, delegating to the vec implementation using an explicit conversion. But doing this for all parameter combinations will become tedious, particularly for functions with many such parameters. So I'm not interested in solutions where I have to duplicate code for every parameter combination of every function.
It appears that neither the conversion constructor nor the cast operator are sufficient to achieve this. At least my gcc 4.7.1 reports no matching function call, although it does name the desired function in a notice, stating that ‘point’ is not derived from ‘vec<d>’.
There is no direct way to get the conversion from point to vec<2>, because at the time when the function call foo(v1,p1) is processed, a function foo that expects a vec<2> as second argument does not exist yet. It's just a function template, and in order for this to be instantiated to a foo(const vec<2> &,const vec<2> &), a function call with these exact argument types would have to be given.
In order for the code to work, the compiler would have to guess both how to instantiate the template parameters, and what type the point argument to convert to. This is too much in the general case (although in your particular code it appears simple, because there is no other possible way to interpret the intent of the programmer).
In terms of solving this, the only thing I can think of is to create highly templated conversion functions:
template <typename T>
struct make_vec
{ };
template <unsigned d>
struct make_vec<vec<d>>
{
static constexpr unsigned dim = d;
using type = vec<dim>;
static const type &from(const type &v)
{ return v; }
};
template <>
struct make_vec<point>
{
static constexpr unsigned dim = 2;
using type = vec<dim>;
static type from(const point &p)
{ return type(p); }
};
template <typename T>
typename make_vec<typename std::decay<T>::type>::type make_vec_from(T&& arg)
{ return make_vec<typename std::decay<T>::type>::from(std::forward<T>(arg)); }
And then implement the foo and bar functions as general templates (accepting all kinds of types, not only vec<d>, using make_vec defined above to convert the given types to the right kind of vec<d>):
namespace detail {
/* Your original implementation of foo. */
template<unsigned d> vec<d> foo(vec<d>, vec<d>) {
return vec<d>(/* ... */);
}
}
/* Templated version of foo that calls the conversion functions (which do
nothing if the argument is already a vec<d>), and then calls the
foo() function defined above. */
template <typename T, typename... Ts>
typename make_vec<typename std::decay<T>::type>::type foo(T&& arg, Ts&&... args)
{ return detail::foo(make_vec_from(arg),make_vec_from(args)...); }
In the case of bar you also need a way to calculate the return type, which is vec<d1+d2+d3...>. For this, a sum calculator is required, also templated:
template <typename... Ts>
struct dsum {
static constexpr unsigned value = 0;
};
template <typename T, typename... Ts>
struct dsum<T,Ts...> {
static constexpr unsigned value = make_vec<typename std::decay<T>::type>::dim + dsum<Ts...>::value;
};
Then, the return type of bar() is vec<dsum<T,Ts...>::value>.
A fully working example is here: http://liveworkspace.org/code/nZJYu$11
Not exactly simple, but might be worth it if you really have extremely many different combinations of arguments.
I am trying to build a statically bound delegate class, where the member function is bound at compile time, thereby aiding optimisation.
I have the following code which works exactly how I want it to:
#include <iostream>
namespace thr {
template<typename T, T func>
struct delegate;
template<typename R,
typename C,
typename... A,
R (C::* mem_fun)(A...)>
struct delegate<R(C::*)(A...), mem_fun>
{
delegate(C* obj_)
: _obj(obj_)
{}
R operator()(A... a)
{
return (_obj->*mem_fun)(a...);
}
private:
C* _obj;
};
} // namespace thr
struct foo
{
double bar(int i, int j)
{
return (double)i / (double)j;
}
};
int main()
{
foo f;
typedef thr::delegate<decltype(&foo::bar), &foo::bar> cb;
cb c(&f);
std::cout << c(4, 3);
return 0;
}
However, the usage is not very elegant:
thr::delegate<decltype(&foo::bar), &foo::bar>
I would like to use a function template which deduces the template parameters and returns a delegate instance; something along the lines of (this code does not compile):
template<typename C, typename T, T func>
thr::delegate<T, func> bind(T func, C* obj)
{
return thr::delegate<decltype(func), func>(obj);
}
This would allow for more elegant syntax:
auto cb = bind(&foo::bar, &f);
Is it possible to deduce a non-type parameter in a function template?
Is what I'm trying to achieve even possible?
Would std::function help? http://www2.research.att.com/~bs/C++0xFAQ.html#std-function Your example looks quite close.
I think the compiler supplied STL does pretty horrible things to make it work smoothly. You may want to have a look at as an example before giving up.
Edit: I went out and tried what you try to accomplish. My conclusion is a compile error:
The return type of the bind (delegate) must name the pointer to member because it is your own requirement.
bind should accept the name of the pointer to member to be elegant (i.e. your requirement)
Compiler requires you to not shadow the template parameter with a function parameter or use the name in both parameters and return type.
Therefore one of your requirements must go.
Edit 2: I took the liberty of changing your delegate so bind works as you wish. bind might not be your priority though.
#include <iostream>
namespace thr {
template<typename C,typename R,typename... A>
struct delegate
{
private:
C* _obj;
R(C::*_f)(A...);
public:
delegate(C* obj_,R(C::*f)(A...))
: _obj(obj_),_f(f)
{}
R operator()(A... a)
{
return (_obj->*_f)(a...);
}
};
} // namespace thr
template<class C,typename R,typename... A> thr::delegate<C,R,A...> bind(R(C::*f)(A...),C* obj){
return thr::delegate<C,R,A...>(obj,f);
}
struct foo
{
double bar(int i, int j)
{
return (double)i / (double)j;
}
};
int main()
{
foo f;
auto c = bind(&foo::bar, &f);
std::cout << c(4, 6);
return 0;
}
It is possible to deduce other entities than types in a function signature, but function parameters themselves cannot then be used as template parameters.
Given:
template <size_t I> struct Integral { static size_t const value = I; };
You can have:
template <size_t N>
Integral<N> foo(char const (&)[N]);
But you cannot have:
Integral<N> bar(size_t N);
In the former case, N as the size of the array is part of the type of the argument, in the latter case, N is the argument itself. It can be noticed that in the former case, N appeared in the template parameters list of the type signature.
Therefore, if indeed what you want is possible, the member pointer value would have to appear as part of the template parameter list of the function signature.
There may be a saving grace using constexpr, which can turn a regular value into a constant fit for template parameters:
constexpr size_t fib(size_t N) { return N <= 1 ? 1 : fib(N-1) + fib(N-2); }
Integral<fib(4)> works;
But I am not savvy enough to go down that road...
I do however have a simple question: why do you think this will speed things up ? Compilers are very good at constant propagation and inlining, to the point of being able to inline calls to virtual functions when they can assess the dynamic type of variables at compilation. Are you sure it's worth sweating over this ?
I am attempting to write a function which will operate on a std::map of any key and class pointer given to it, and create a new std::map with an index based on the return value of a function in the class. Essentially, a template function to re-index a map based on a function in its contained class. However, I am having compiler errors when trying to invoke the function.
template<class AnyType, class ValueType, class FunctionType>
AssocArray<FunctionType,ValueType> reindex( const AssocArray<AnyType, ValueType>& original, FunctionType (*getterFunction)() ) {
AssocArray<FunctionType, ValueType> ret;
FunctionType index;
for(typename AssocArray<AnyType,ValueType>::const_iterator it = original.begin(); it!=original.end(); it++) {
index = ((*it->second).*getterFunction)();
ret[index] = it->second;
}
return ret;
}
Invoked by:
floatIndexed = reindex( intIndexed, &test::getB );
Where getB is of float type.
This results in the compiler error:
src/World.cpp:78:50: error: no matching function for call to ‘reindex(std::map<int, onathacar::test*>&, float (onathacar::test::*)())’
src/World.cpp:78:50: note: candidate is:
./include/Types.h:123:36: note: template<class AnyType, class ValueType, class FunctionType> std::map<PreservedType, ValueType> onathacar::reindex(const std::map<LookupType, ValueType>&, FunctionType (*)())
I have tried different variations of this, including using "FunctionType (ValueType::*getterFunction)()" and changing "AssocArray" to "AssocArray". The only one which worked added a fourth template argument:
template<class AnyType, class ValueType, class FunctionType, class SomeType>
AssocArray<FunctionType,ValueType> reindex( const AssocArray<AnyType, ValueType>& original, FunctionType (SomeType::*getterFunction)() ) {
However, this seems like it would potentially allow functions that are not actually members of ValueType to be called, and so I would prefer some other option. I am not even sure what is wrong, as it appears the templates match, at least with the addition of "ValueType::". Why does the call not match the template, and is there a way to fix it without a fourth templated type?
For more context, Header Containing Implementation and Calling Function.
You have two problems. The first is that reindex implies that the value types are values, but you use them as pointers:
AssocArray<float, test*> floatIndexed;
floatIndexed = reindex( intIndexed, &test::getB );
The second is that reindex's second parameter needs to be declared as a member function, not a free function. So reindex should look like this:
template<class AnyType, class ValueType, class FunctionType>
AssocArray<FunctionType,ValueType *> reindex( const AssocArray<AnyType, ValueType *>& original, FunctionType (ValueType:: *getterFunction)() ) {
AssocArray<FunctionType, ValueType*> ret;
FunctionType index;
for(typename AssocArray<AnyType,ValueType*>::const_iterator it = original.begin(); it!=original.end(); it++) {
index = ((*it->second)->*getterFunction)();
ret[index] = it->second;
}
return ret;
}
It seems that you are trying to use your rindex() function with members but your function is declared to use non-members. This won't work. The reason this won't work is that the you need an object to access either function or data members of a class.
template<class A, class B>
class X{
public:
};
class Y{
public:
int func() { return 42; }
};
template<class A, class B, class C>
X<C,B> reindex( const X<A, B>& original, C (B::*getterFunction)() ) {
X<C, B> x2;
cout << "hello" << endl;
return x2;
}
int main() {
X x1;
reindex(x1,&Y::func);
return 0;
}
This works and gives perfectly valid results.
The problem with your call AssocArray intIndexed, is the fact that you are trying to pass &test::getB as the getter function, which assumes valueType = test, where as your actual value type, is test*.