Last active
June 10, 2024 22:36
-
-
Save talybin/c4856c217ad390eff98b24dbf7a000fb to your computer and use it in GitHub Desktop.
Attempt to detect if function has variadic number of arguments
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <utility> | |
struct any_type | |
{ | |
template <class T> | |
constexpr operator T(); // non explicit | |
}; | |
namespace detail | |
{ | |
// from TS (https://en.cppreference.com/w/cpp/experimental/is_detected) | |
template<class Default, class AlwaysVoid, template<class...> class Op, class... Args> | |
struct detector | |
{ | |
using value_t = std::false_type; | |
using type = Default; | |
}; | |
template<class Default, template<class...> class Op, class... Args> | |
struct detector<Default, std::void_t<Op<Args...>>, Op, Args...> | |
{ | |
using value_t = std::true_type; | |
using type = Op<Args...>; | |
}; | |
template<class Default, template<class...> class Op, class... Args> | |
using detected_or = detector<Default, void, Op, Args...>; | |
template< class Default, template<class...> class Op, class... Args > | |
using detected_or_t = typename detected_or<Default, Op, Args...>::type; | |
// -------------------------------- | |
template <size_t N, class T> | |
using index_type = T; | |
template <class F, class> | |
struct function_ret_type; | |
template <class F, size_t... I> | |
struct function_ret_type<F, std::index_sequence<I...>> | |
{ | |
// Return any_type if F is NOT callable with given number of arguments | |
using type = detected_or_t< | |
any_type, | |
std::invoke_result_t, F, index_type<I, any_type>... | |
>; | |
}; | |
} // namespace detail | |
// Test if function is callable with sample number of arguments. | |
// Asuming that function has variadic number of arguments if all | |
// samples are callable. | |
template <class F> | |
struct is_variadic_arg_function { | |
private: | |
template <size_t N> | |
using fn_ret_t = typename | |
detail::function_ret_type<F, std::make_index_sequence<N>>::type; | |
template <class> struct test; | |
template <size_t... I> | |
struct test<std::index_sequence<I...>> { | |
// True if all samples are callable (has return type) | |
static constexpr bool value = (!std::is_same_v<any_type, fn_ret_t<2^I>> && ...); | |
}; | |
public: | |
// Test 7 samples (1, 2, 4, 8, 16, 32 and 64 number of args) | |
static constexpr bool value = test<std::make_index_sequence<7>>::value; | |
}; | |
template <class F> | |
constexpr inline bool is_variadic_arg_function_v = is_variadic_arg_function<F>::value; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Tests: