Я предлагаю zero_sequence
совершенно другое: не struct
, а using
на основе decltype()
, std::declval()
и только объявленной вспомогательной функции (следуя примеру std::declval()
.
Я имею в виду ... если вы определите следующую вспомогательную функцию
template <std::size_t ... Is>
constexpr auto zeHelper (index_sequence<Is...> const &)
-> decltype( index_sequence<(Is,0u)...>{} );
zero_sequence
можно определить как
template <typename T>
using zero_sequence = decltype(zeHelper(std::declval<T>()));
и вы можете отклонить a0
и b0
A0 a0;
B0 b0; // now works
и без проблем компилировать также
static_assert( std::is_same<A0, B0>::value, "!" );
Я озадачен тем, почему это происходит [...] Я не понимаю, почему два случая различны
Проблема с вашей zero_sequence
спецификацией структуры шаблона
template<size_t...I>
struct zero_sequence<index_sequence<I...>> : index_sequence<(I*0u)...>{};
в том, что есть также универсальная версия (не реализована, но есть)
template<typename> struct zero_sequence;
Таким образом, когда вы используете index_sequence
в качестве параметра шаблона для zero_sequence
, реализованная специализация совпадает и выбирается.
Но когда вы используете make_index_sequence
, который наследуется от index_sequence
и может быть преобразован в index_sequence
, но не является index_sequence
, специализация не соответствует и универсальная (не реализованная) версия из zero_sequence
выбран.
Проходя через функцию, zeHelper()
, которую я предлагаю, или что-то подобное, избегает этой проблемы, потому что make_index_sequence
можно преобразовать в index_sequence
.