I'm trying to understand how the Qt5 framework's Signals and Slots mechanism does type checking on function arguments.
I've provided a summary of the section of code I'm interested in. The only thing I'm having trouble understanding is the following template specialization. How does the compiler decide to instantiate this? I especially don't understand when template parameter list template< typename Arg1, typename Arg2, typename... Tail1, typename... Tail2 > is considered.
template< typename Arg1, typename Arg2, typename... Tail1, typename... Tail2 >
struct Test< List< Arg1, Tail1... >, List< Arg2, Tail2... > > {
enum { value = ArgsCompat< Arg1, Arg2 >::value && Test< List< Tail1... >, List< Tail2... > >::value };
};
namespace Test {
template< typename... >
struct List{};
template< typename H, typename... T >
struct List< H, T... >{
typedef H Head;
typedef List< T... > Tail;
};
template< typename T > struct RemoveRef { typedef T type; };
template< typename T > struct RemoveRef< T& > { typedef T type; };
template< typename Arg1, typename Arg2 >
struct ArgsCompat {
static int test( const typename RemoveRef< Arg2 >::type & );
enum { value = true };
};
template< typename Elem1, typename Elem2 > struct Test { enum { value = false}; };
template<> struct Test< List<>, List<> > { enum { value = true }; };
template< typename Arg1> struct Test< Arg1, List<> > { enum { value = true }; };
template< typename Arg1, typename Arg2, typename... Tail1, typename... Tail2 >
struct Test< List< Arg1, Tail1... >, List< Arg2, Tail2... > > {
enum { value = ArgsCompat< Arg1, Arg2 >::value && Test< List< Tail1... >, List< Tail2... > >::value };
};
}
int main( void ) {
static_assert( Test::Test< Test::List<>, Test::List<> >::value, "" );
static_assert( Test::Test< Test::List< char >, Test::List< char > >::value, "" );
static_assert( Test::Test< Test::List< char, int, double >, Test::List< char, int, double > >::value, "expected true" );
return 0;
}```