Compiling this:
template < class T, class Y, class ...Args >
struct isSame
{
static constexpr bool value = std::conditional<
sizeof...( Args ),
typename std::conditional<
std::is_same< T, Y >::value,
isSame< Y, Args... >, // Error!
std::false_type >::type,
std::is_same< T, Y > >::type::value;
};
int main()
{
qDebug() << isSame< double, int >::value;
return EXIT_SUCCESS;
}
Gives me this compiler error:
error: wrong number of template arguments (1, should be 2 or more)
The issue is that isSame< double, int > has an empty Args parameter pack, so isSame< Y, Args... > effectively becomes isSame< Y > which does not match the signature.
But my question is: Why is that branch being evaluated at all? sizeof...( Args ) is false, so the inner std:conditional should not be evaluated. This isn't a runtime piece of code, the compiler knows that sizeof..( Args ) will never be true with the given template types.
If you're curious, it's supposed to be a variadic version of std::is_same, not that it works...
You have an error because the type has to be correct when used as template parameter.
You may use template specialization to solve your issue, something like:
#include <type_traits>
template <typename ... Ts> struct are_same;
template <> struct are_same<> : std::true_type {};
template <typename T> struct are_same<T> : std::true_type {};
template <typename T1, typename T2, typename... Ts>
struct are_same<T1, T2, Ts...> :
std::conditional<
std::is_same<T1, T2>::value,
are_same<T2, Ts...>,
std::false_type
>::type
{};
static_assert(are_same<char, char, char>::value, "all type should be identical");
static_assert(!are_same<char, char, int>::value, "all type should not be identical");
Since C++17, you might do:
template <typename T, typename... Ts>
using are_same = std::bool_constant<(std::is_same_v<T, Ts> && ...)>;