Yay, another question consisting of a random sequence of C ++ terms!
Usually we create a class Callable, implementing operator() . But you can also do this by implementing a user-defined conversion to a function pointer or reference type. Instead of using perfect forwarding, the transform function can return a pointer to a function that is then called with the original argument list.
struct call_printf { typedef int printf_t( char const *, ... ); operator printf_t & () { return std::printf; } };
http://ideone.com/kqrJz
As far as I can tell, the typedef above is a syntactic necessity. The name of the conversion function is formed from the type-specifier-seq, which does not allow constructing such a construct as int (*)() . This will require an abstract declarator. Presumably, the reason is that such type names become more complex, and complex constructs used as object names are difficult to parse.
Template conversion functions are also allowed, but template arguments must be inferred because they are not explicitly specified. (This will defeat the whole point of implicit conversion.)
Question # 1: In C ++ 03, is there no way to specify a function conversion operator pattern? Apparently, there was no way to allow template arguments (i.e., Name them in the derived context) in a valid function pointer type.
Here is the equivalent link from C ++ 11, ยง13.3.1.1.2 / 2 [over.call.object]. This is essentially the same from C ++ 03:
In addition, for each implicit conversion function declared in T form
operator conversion-type-id () cv-qualifier attribute-specifier-seqopt;
where the cv qualifier is the same cv qualification as the higher cv qualification than cv, and where the transform type identifier denotes the type "function pointer (P1, ..., Pn) returning R", or type "reference to a pointer to a function (P1, ..., Pn) returning R" or type "reference to a function (P1, ..., Pn) returning R", a surrogate call function with a unique function of calling a name and having form
R call-function ( conversion-type-id F, P1 a1, ... ,Pn an) { return F (a1,... ,an); }
also considered as a candidate function. Similarly, surrogate call functions are added to the set of candidate functions for each implicit conversion function declared in the base class T, provided that the function is not hidden inside T by another intermediate declaration.
Question # 2: In C ++ 11, is it possible to specify such a conversion using the default template argument? It is useful for SFINAE. The only difference here from the above example is that the transform type identifier only represents a reference to the function after the instance is created, because it is a dependent type (despite the invariance). This disables GCC and skips the member template.
enum { call_alternate = true; } struct call_switch { template< bool en = call_alternate > operator typename std::enable_if< en, decltype( fn_1 ) & >::type () { return fn_1; } template< bool en = ! call_alternate > operator typename std::enable_if< en, decltype( fn_2 ) & >::type () { return fn_2; } };
We also have nickname templates. It seems that substitution of aliases is preceded by instantiation, given the example in ยง14.5.7 / 2, in which process declarations conflict. In GCC 4.7, this code at least creates an instance of the declaration, but then it calls the strange "candidate expects 2 arguments, 2 provided" error.
template< typename t > using fn_t = void (&)( t ); struct talk { template< typename t > operator fn_t< t >() { return fn; } }; int main() { talk()( 3 ); }