I've been exploring many of the new features of C++ 11 in Visual Studio 2013 Pro. So far I gotta say it kicks ass, but I hit a snag in my research and I was hoping I could raise mu hand and get some help. (Big fan of this site, first time posting, sorry if code isn't set up right).
Currently, I'm trying to create a generic method of binding a function and/or member function ( operator ()
) to an encapsulated instance of std::function.
I'm using a variadic template argument to deal with variable argument lists, drawing the number of arguments via the size of the variadic, and using the value in compile-time recursion in order to pump/return the correct number of placeholders into the bind operation.
Because std::bind
needs an instance and not a type, the compile-time recursion helpers are just returning instances of std::_Ph <N>
. I use a specialization of the helper ( std::_Ph<1>
) as a delimiter, otherwise it just turns into an infinite loop that floods the call-stack during compilation.
Here is an example of the experiential code I'm working with:
//Nothing special, just a polymorphic base
class iObject {
public:
virtual ~iObject () {};
};
/*Again nothing special, just a default null object implementation of an object that overloads operator ()*/
template < typename RETURN_TYPE, typename ... ARGS >
class BaseCall : public iObject {
public:
~BaseCall () {};
virtual RETURN_TYPE operator () ( ARGS ... args ) {
return 0;
};
};
//One more bit of testing fodder, a concrete implementation of BaseCall
template < typename RETURN_TYPE, typename ... ARGS >
struct SampleMax : public BaseCall < RETURN_TYPE, ARGS ... > {
private:
/*deals with error C2903: 'result' : symbol is neither a class template not a function template*/
typedef RETURN_TYPE result_type;
//Inverted template method + trailing return
protected:
//Function assumes we are working with a sorted STL container
template < typename FIRST_ARG >
inline auto Implementation ( FIRST_ARG & Sample ) -> result_type {
return * ( Sample.rbegin() );
};
public:
/*For all public operator () members like this the code would be the same
result_type operator () ( ARGS ... args ) {
return Implementation ( args ... );
};
};
//My compile-time helpers
//Got the idea from here:
//http://stackoverflow.com/questions/8759872/compile-time-recursion-and-conditionals
template < int N >
std :: _Ph < N > * CTRecursivePlaceholder () {
return new std :: _Ph < N - 1 >;
};
//Specialization
template <>
std :: _Ph < 1 > * CTRecursivePlaceholder < 1 > () {
return new std :: _Ph < 1 >;
};
//Here's the beef
template < typename RETURN_TYPE, typename ...ARGS >
class Experiment {
public: /*Ideally private, but for testing purposes it doesn't really matter right now*/
std :: function < RETURN_TYPE ( ARGS ... ) Receiver;
public:
Experiment () {
Receiver = std :: bind ( BaseCall < RETURN_TYPE, ARGS ... > (), * ( CTRecursivePlaceholder < ( sizeof ... ( ARGS ) ) > () ) );
};
virtual ~Experiment () {};
};
PROBLEM #1: In instances where only a single argument is required, creating an instance works normally, as well as binding and calling a standalone function:
/*pretend a vector of doubles called vec exists so I don't have to write it ;)*/
//...somewhere in a header...
double func ( std :: vector < double > & k )
{ return 1.0f; };
//...somewhere in a source file...
Experiment < double, std :: vector < double > & > exp; //<-- instantiates just fine
exp.Receiver = & func; //works
exp.Receiver ( vec ); //works
However, when I try to assign the std::function data member to a child of BaseCall such as my SampleMax functor like so:
SampleMax < double, std :: vector < double > & > max;
exp.Reciever = & max; //no go
I get error C2064: term does not evaluate to a function taking 1 arguments
. The error originates from , inside of the xrefwrap header.
If I use placeholders outright inside of the Experiment constructor, it'll work.
PROBLEM #2: Across the board ( standalone functions & member functions ), if I try to create an instance of Experiment with a signature of two arguments or more, like so:
//...somewhere in a source file...
Experiment < double, std :: vector < double > &, std :: vector < double > & > exp;
I get the following error ( C2440 ):
'return' : cannot convert from 'std :: _Ph < 1 > *' to 'std :: _Ph < 2 > *'
If I remember correctly, specializations will always take precidence to the compiler over template definitions, so it could be that it's going after the specialization instead of the template definition.
I'm also not so sure about the 'N - 1' statement in the template definition of std::_Ph, because it should be performing the arithmetic before it creates the instance, but that's how the example ran through it so I did the same.
Pardon any typo's, I wrote this whole thing on my phone, and thanks for any help you can give!