Coding questions · OpenAI
Implement compile-time function type verification
This question evaluates proficiency in C++ template metaprogramming, type traits, SFINAE and Concepts for compile-time callable signature verification, including handling of noexcept, cv/ref qualifiers and implicit conversions.
Implement a C++20 compile-time utility to verify whether a callable matches a target function type. Requirements: create a primary template is_callable_with_signature<Fn, R(Args...)> that yields true if Fn is invocable with Args... and the return type is convertible to R; provide two implementations— (1) SFINAE/traits-based and (2) concepts/requires-based; support free functions, lambdas, functors with overloaded operator(), member function pointers, and std::function; include minimal tests with static_assert and examples that should fail to compile if the signature does not match; discuss handling noexcept, cv/ref qualifiers, and implicit conversions.
Part 1: Traits-Style Callable Signature Match
You are given the list of callable signatures exposed by a callable object. Think of this as a simplified runtime version of C++ traits such as is_invocable_r.
Each string in 'signatures' represents one overload of the callable. The origin of the overload does not matter: a free function, lambda, functor, member-function pointer, or std::function can all be represented the same way.
A target signature has the form '(A1,A2,...)->R'. A candidate overload matches the target if:
- It has the same number of parameters.
- Every target argument type can be implicitly converted to the candidate parameter type.
- The candidate return type can be implicitly converted to the target return type.
Supported types are: 'bool', 'int', 'long', 'double', 'string', and 'void'.
Allowed implicit conversions are:
- exact type to itself
- bool -> int, long, double
- int -> long, double
- long -> double
- void is only convertible to void
- no other conversions are allowed
Return True if at least one candidate overload matches the target signature; otherwise return False.
Constraints
- 0 <= len(signatures) <= 10000
- Each signature string has length between 4 and 100
- All signatures are well-formed
- Types only come from: bool, int, long, double, string, void
- Only the listed implicit conversions are allowed
Examples
Example 1
Input: (['(int)->long'], '(int)->double')
Output: True
Explanation: The argument type matches exactly, and the candidate return type long can be widened to double.
Example 2
Input: (['(double)->int', '(string)->int'], '(int)->long')
Output: True
Explanation: The first overload matches because int can convert to double and int can convert to long on return.
Hints
- Parse each signature into an argument list and a return type. Overloads are just multiple candidate strings.
- Model implicit conversion as a directed rule set or numeric rank order, then test every parameter position plus the return type.
Part 2: Concepts-Style Callable Signature Match with Qualifiers
Now extend the matcher to simulate a stricter concepts/requires-style check.
Each candidate overload and the target signature begin with a bracketed qualifier list, followed by the function type. The format is: '[q1,q2,...](A1,A2,...)->R'
Examples:
- '[](int)->double'
- '[const,&,noexcept](int)->long'
- 'noexcept->void'
Supported qualifiers are:
- 'const'
- '&'
- '&&'
- 'noexcept'
A candidate overload matches the target if all of the following hold:
- It has the same number of parameters.
- Every target argument type can be implicitly converted to the candidate parameter type.
- The candidate return type can be implicitly converted to the target return type.
- If the target requires 'const', the candidate must include 'const'.
- If the target requires 'noexcept', the candidate must include 'noexcept'.
- If the target requires '&', the candidate must include '&'.
- If the target requires '&&', the candidate must include '&&'.
- If the target omits a qualifier, the candidate may have it or not.
Use the same type system and implicit conversion rules as in Part 1.
Return True if at least one overload matches; otherwise return False.
Constraints
- 0 <= len(signatures) <= 10000
- Each signature string has length between 6 and 120
- All signatures are well-formed
- Types only come from: bool, int, long, double, string, void
- Qualifiers only come from: const, &, &&, noexcept
- A signature contains at most one of '&' and '&&'
- Only the listed implicit conversions are allowed
Hints
- Treat the bracketed qualifier list as a set of properties. The target's qualifiers are requirements; the candidate may have extra ones.
- After qualifier matching, reuse the same argument-conversion and return-conversion logic from Part 1.