GCC и clang не согласны с этим кодом.
#include <type_traits>
template <typename T, template <typename...> typename Tpl>
struct storage {
using type_t = T;
template <typename... Args>
using storage_tpl = Tpl<Args...>;
};
template <typename T, template <typename...> typename>
struct F{
constexpr static int x = 1;
};
template <typename T >
struct F<T, std::void_t>{
constexpr static int x = 2;
};
int f() {
using S = storage<int, std::void_t>;
static_assert(F<int, S::storage_tpl>().x == 2);
return F<int, S::storage_tpl>().x;
}
Согласно clang S::storage_tpl
не является std::void_t
;следовательно, он выбирает основной шаблон F вместо частичной специализации и, следовательно, утверждения.
На первый взгляд, похоже, что GCC прав, потому что понимает, что вложенный шаблон является просто псевдонимом для std::void_t
, номожет быть, он слишком умный, и стандарт требует, чтобы S::storage_tpl
и std::void_t
были двумя разными шаблонами.
Кто прав?