Skip to content

Specification of function qualifier traits for function pointer and reference types #177

@willwray

Description

@willwray

The callable_traits specifications of is_QUAL_member and is_noexcept traits seem inconsistent with similar std traits which do not see through reference or pointer (for QUAL in const, volatile, cv, reference, lvalue_reference, rvalue_reference).

For instance:
std::is_const_v<T&> -> false regardless of T
ct::is_noexcept_v<T&> -> ? - dependent on T

The particular case of is_noexcept is vexing. Should it be spelt is_noexcept_member for consistency with the other is_QUAL_member traits? The simple spelling is_noexcept might be taken as a static version of the noexcept() operator, something like:
template <typename F> inline constexpr bool is_noexcept = noexcept(std::declval<F>()());
(note that such use of noexcept operator is not viable in general - it assumes F is callable with no args, falling down when args are needed, but expanding Args... means also checking for all 48 abominable combos by which time the noexcept qualifier is known anyhow).

These callable_traits smell like they are trying to do too much:

is_QUAL_member<T>::value / is_noexcept<T>::value is true when either:
T is a function type, function pointer type, function reference type, or member function pointer type where the function has a QUAL / noexcept specifier
T is a function object with a non-overloaded operator(), where the operator() has a QUAL / noexcept specifier

(That last line is very specific - checking for no-args function object.)

In the Input/Output examples:

is_noexcept<int(* const &)() noexcept> -> true

In this case the trait is stripping off & and * const to expose the function signature and its qualifiers. The documented description of the behaviour above doesn't mention this recursive stripping.

More vexing - should is_noexcept default to true for non-function types? Is a non-function type noexcept or not? (The is_noexcept_member spelling would make this more clear.)

I think that there's value in exposing the underlying checks themselves without the recursive pointer/reference unwrapping.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions