In this code, I'm trying to generalize Test from using Arg to using Args.... The problem is the default template argument. What I have below compiles, except when I uncomment the commented-out line in main():
#include <iostream>
#include <type_traits>
struct A {
void foo(int) const {}
void foo(int, bool, char) const {}
};
template <typename...> struct voider { using type = void; };
template <typename... Ts>
using void_t = typename voider<Ts...>::type;
template <typename T, typename Arg, typename = void_t<T>>
struct Test : std::false_type {};
template <typename T, typename Arg>
struct Test<T, Arg, void_t<decltype(std::declval<T&>().foo(std::declval<Arg>()))>> :
std::true_type {};
// Trying to generalize Test with Args... instead of Arg
template <typename T, typename, typename... Args> struct Check;
template <typename T, typename... Args>
struct Check<T, void_t<T>, Args...> : std::false_type {};
template <typename T, typename... Args>
struct Check<T, void_t<decltype(std::declval<T&>().foo(std::declval<Args>()...))>, Args...>
: std::true_type {};
template <typename T, typename... Args>
using CheckArgs = Check<T, void_t<T>, Args...>;
int main() {
std::cout << std::boolalpha << Test<A, int>::value << '\n'; // true
// std::cout << CheckArgs<A, int, bool, char>::value << '\n'; // ambiguous
}
The last line in main() is ambiguous. Firstly, why is it ambiguous, while the first line in main() is not? And secondly, how to fix the code so that the last line in main will compile (it is supposed to evaluate to true since int, bool, char are arguments of A::foo)?
decltype(std::declval<T&>().foo(std::declval<Arg>())cannot be evaluated, i.e.A::foodoes that not have that particularArgas argument (which meansTest<A,Arg>::valuemust evaluate to false). I really do think VS2015 is bugged in its output here. But as for compiling/not compiling the second line, I don't know if it is GCC or VS2015 that is buggy. - prestokeys