The following code complains on the line with dp1
"term does not evaluate to a function taking 0 arguments". I expect that dp1 would match the IsInstantiation
specialization of Dispatch
, but it errors.
How would I change this code so that it will work as I expect? I am using VS2015 and cannot use std::invoke
or std::is_invokable
.
#include <type_traits>
template <typename>
class TemplateA {};
struct Callable
{
void operator()() {};
};
template <typename F, typename... Args>
constexpr auto Invoke(F &&f, Args &&... args)
{
return f(std::forward(args)...);
}
template <template<typename...> class TT, typename T>
struct IsInstantiation : std::false_type {};
template <template<typename...> class TT, typename... Ts>
struct IsInstantiation<TT, TT<Ts...>> : std::true_type {};
template <typename, typename = void>
struct HasNoArgs : std::false_type {};
template <typename T>
struct HasNoArgs<T, std::void_t<decltype(Invoke(T{}))>> : std::true_type {};
template <typename T1, typename = void>
class Dispatch;
template <typename T1>
class Dispatch<T1, std::enable_if_t<HasNoArgs<T1>::value>> {};
template <typename T1>
class Dispatch<T1, std::enable_if_t<IsInstantiation<TemplateA, T1>::value>> {};
int main(int argc, char *argv[])
{
Dispatch<TemplateA<int>> dp1;
Dispatch<Callable> dp2;
return 0;
}