. -, , , if - , -, , , , . , , .
. , ++ 17:
template<typename, typename = void>
struct is_callable : std::false_type {};
template<typename F, typename... Args>
struct is_callable<F(Args...), void_t<decltype(std::declval<F>()(std::declval<Args>()...))>> : std::true_type {};
std::enable_if:
struct Formatter {
template<typename F, typename... Args>
auto format(F func, Args&&... args) -> std::enable_if_t<is_callable_v<F(Args...)>> {
std::cout << func(std::forward<Args>(args)...);
std::cout << std::endl;
}
template<typename T>
auto format(T&& value) -> std::enable_if_t<!is_callable_v<T()>> {
std::cout << std::forward<T>(value);
std::cout << std::endl;
}
};
void_t :
template<typename...>
using void_t = void;
: Live at coliru
, ++ 17 constexpr if std::is_invocable:
struct Formatter {
template<typename F, typename... Args
void format(F&& param, Args&&... args) {
if constexpr (std::is_invocable_v<F, Args...>) {
std::cout << std::invoke(std::forward<F>(param), std::forward<Args>(args)...);
} else {
std::cout << std::forward<F>(param);
log(std::forward<Args>(args)...);
}
}
};