How to create an alias for a noexcept function pointer?

I would like to do this:

using function_type = void (*)(void*)noexcept; 

But I get an error: "Exception specifications are not allowed in type aliases." (clang in version 6.1 of Xcode)

Is there a workaround for creating an alias with a noexcept specifier?

I am looking for something that works according to the language (and not the extension) for cross-platform capabilities.

+9
c ++ c ++ 11 noexcept function-pointers
source share
4 answers

The standard explicitly prohibits the specification of exceptions from appearing in a typedef or alias declaration. But it also states that the exception specifier may appear as a function pointer.

ยง15.4 / 2 [except.spec]

An exception specification should only appear on a function declaration for a function type, a pointer to a function type , a reference to a function type, or a pointer to a member function type that is a top-level declaration type or definition, or that type that appears as a parameter or return type in function declaration. The exception specification should not appear in a typedef declaration or alias declaration .

And if a function pointer has an exception specification, then a function type that has a compatible exception specification must always be assigned to this function pointer.

ยง15.4 / 5

... A similar restriction applies to the assignment and initialization of function pointers, member function pointers and function references: the target must allow at least the exceptions allowed by the original value in assignment or initialization . ...

Using these two, you can get the noexcept specification on the function pointer type in a workaround.

 void (*foo_ptr)(void *) noexcept = nullptr; using function_type = decltype(foo_ptr); 

Now you cannot assign a function without the noexcept(true) specification to a function pointer of type function_type . clang will not be able to compile the error code

error: specification of exceptions for purposes is not superset of source

+9
source share

An alternative to the Praetorian answer that does not include a variable declaration:

 void unused_function(void*)noexcept; using function_type = decltype(&unused_function); 

unused_function declared but not defined.

+3
source share

As a consequence of this answer, the template you are looking for is simple:

 using function_type = decltype(std::declval<function_type_declaration>()); 

Those.

 #include <utility> //... using function_type = decltype(std::declval<void (*)(void*)noexcept>()); 

This does not work with extern communication, including extern "C" , that is:

 // INVALID using function_type = decltype(std::declval<extern "C" void(*)(void)>()); // WORKAROUND extern "C" void function_type_dummy(void); using function_type = decltype(&function_type_dummy); 
+2
source share

To further simplify this answer, we can use the type trait std::add_pointer as follows:

 using function_type = std::add_pointer_t<void(void*) noexcept>; 

From the reference documentation (highlighted mine):

If T is a reference type, it provides the typedef type of the member, which is a pointer to the type.

Otherwise, if T names the type of the object, the type of the function that is not cv- or non-qualified ref , or the (possibly cv- qualified) type void, provides the typedef of the member, which is the type of T *.

Otherwise ( if T is a type of function cv- or ref-qualified ), provides the typedef type of the member, which is type T.

In other words, std::add_pointer implemented in such a way that it is compatible with signature function expressions as arguments to a C ++ template .

The extern "C" restriction still applies, so you have to use the workaround in the answer I linked.

0
source share

All Articles