Transformation pattern function for function pointer function

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 ); } 
+8
c ++ type-conversion c ++ 11 functor templates
source share
1 answer

Question # 1: In C ++ 03, is there no way to specify a template for a function conversion operator? Apparently, there was no way to allow template arguments (i.e., Name them in the derived context) in a valid function pointer type.

Yes, that's right.

Question # 2: In C ++ 11, can such a conversion be specified using the default template argument?

It may, and you can also use alias patterns, but you cannot use such a transform function pattern to create surrogate call functions. You can use it to convert a class object to function pointers in implicit conversions otherwise.

We also have nickname templates. It seems that the alias replacement takes place before the instance is created, taking into account the example in ยง14.5.7 / 2, where process conflict declarations are declared. 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.

Yes, this is https://groups.google.com/forum/?fromgroups#!topic/comp.std.c++/lXLFBcF_m3c (and caused the DR395 to close), but even if such a conversion function template can work in cases such as void(&p)() = yourClassObject , it will not work for surrogate call functions, because there the conversion function must provide a fixed independent type that the class object is converted at the time the surrogate function is called, but the conversion function template does not provide this type usually (strange things like template<typename = int> operator Identity<void(*)()>(); aside ...).

I think that GCC can incorrectly generate a call-function(void (&)( t ), t) candidate call-function(void (&)( t ), t) with dependent types that still exist, and try to call this candidate, thereby violating some invariant (which may explain the strange message about error - perhaps a defeat } else { ... } unexpectedly somewhere).

+3
source share

All Articles