Convert Variadic Function Pointer

I am writing a library with many function objects whose classes have several operator() overloads that are independent of the state of the classes and do not change it. Now I was trying to get my code to work with many old-style APIs (this is not a random necessity, I actually had to deal with such APIs), and therefore decided to turn the function objects into quotes with any function pointer matching one out of overload. At some point, I realized that I have too many of these transformations for pointer operators to work, and that I would theoretically have to write one variational transform operator. Here is a class that implements such a variational operator:

 struct foobar { template<typename... Args> using fptr_t = void(*)(Args... args); template<typename... Args> operator fptr_t<Args...>() const { return [](Args... args) { // Whatever }; } }; 

As you can see, I used the conversion of lambda to a function pointer to implement the conversion operator, which is not a problem, since every function object that I have has no state. The goal was to use the class as follows:

 int main() { void(*foo)(int) = foobar(); void(*bar)(float, double) = foobar(); } 

g ++ has no problem compiling this code with the expected semantics. However, clang ++ rejects it with a pattern replacement replacement error:

 main.cpp:21:11: error: no viable conversion from 'foobar' to 'void (*)(int)' void(*foo)(int) = foobar(); ^ ~~~~~~~~ main.cpp:11:5: note: candidate function [with Args = int] operator fptr_t<Args...>() const ^ 1 error generated. 

Please note that clang ++ has no problems with such conversion operators if variational patterns are not involved. If I use one parameter of the template, it will have no problems compiling the code. Now, should the code be accepted or rejected by the compiler?

+7
c ++ language-lawyer c ++ 14 function-pointers variadic-templates
source share
1 answer

A lambda can only be converted to a function pointer if it is not captured, so your code should work. This is justified in the standard expressions 5.1.2 / p6 lambda [expr.prim.lambda] ( Emphasis Mine ):

The closure type for a non-generic lambda expression without lambda-capture has a public non-virtual implicit conversion const function to pointer to function with C ++ language linkage (7.5), having the same parameters and return types as the call closure function. The value returned by this conversion function must be the address of the function, which when called has the same effect as calling the closure of the function call function.

Therefore, I would put it as a CLANG error.

As work for CLANG, you can convert it to std::function , as shown below:

 struct foobar { template<typename... Args> using fptr_t = void(*)(Args... args); template<typename... Args> operator std::function<void(Args...)>() const { return [](Args... args) { //... }; } }; int main() { std::function<void(int)> f1 = foobar(); std::function<void(double, float)> f2 = foobar(); f1(1); f2(2.0, 1.0f); } 

Live demo

+1
source share

All Articles