I created a trait struct FnOnArg
to see if Fn can call on Arg
template<typename Fn, typename Arg, typename=void>
struct FnOnArg: std::false_type {};
template<typename Fn, typename Arg>
struct FnOnArg<Fn, Arg, std::void_t<decltype(std::declval<Fn>()(std::declval<Arg>()))>>: std::true_type {};
It can only work on Fn with one argument
I want to create FnOnArgs
like
template<typename Fn, typename... Args, typename=void>
struct FnOnArgs;
but variadic and default template argument both should be the last argument
Any workaround to achieve FnOnArgs
?
You move the dummy template argument typename = void
to have it somewhere before typename... Args
.
This means it can no longer have the default argument (= void
), so you remove it and pass void
explicitly.
You then create another template that wraps this one and adds void
automatically, so you don't have to pass it every time.
template <typename Void, typename Fn, typename ...Args>
struct FnOnArgsLow : std::false_type {};
template <typename Fn, typename ...Args>
struct FnOnArgsLow<std::void_t<decltype(std::declval<Fn>()(std::declval<Args>()...))>, Fn, Args...> : std::true_type {};
// The wrapper can be a variable or a class, whatever you like more.
template <typename Fn, typename ...Args>
static constexpr bool FnOnArgs = FnOnArgsLow<void, Fn, Args...>::value;