1

I've been trying to write a zero_sequence type which either creates an index_sequence of a specified number of zeros or uses an existing index_sequence as to produce a new one with the same number of values, but all zero. I'm perplexed as to why this is happening:

template<typename> struct zero_sequence;
template<size_t...I> 
struct zero_sequence<index_sequence<I...>> : index_sequence<(I*0u)...>{};

int main( int argc, char *argv[] ) {

  using A  = index_sequence<0,1,2,3,4>;
  using B  = make_index_sequence<5>;
  using A0 = zero_sequence<A>;
  using B0 = zero_sequence<B>;

  A a;  B b; 

  cout <<< std::is_same<A,B>::value << endl; // is false

  A0 a0; 
  B0 b0;  // < error implicit instantiation of undefined template
  return 0;
}

I don't understand why the two cases are different (on Mac Clang llvm 9.0.0).

In case it is relevant to explaining this behavior, I am using the following implementation of index_sequence and make_index_sequence in C++11 I think I got it from here:

template<typename Integer, Integer... I>
struct integer_sequence {
  using type = integer_sequence;
  using value_type = Integer;
  static constexpr size_t size() noexcept { return sizeof...(I); }
};

template<size_t... Ints> using index_sequence = integer_sequence<size_t, Ints...>;

template <typename,typename> struct _merge_and_renumber;

template <size_t... I1, size_t... I2>
struct _merge_and_renumber<index_sequence<I1...>,index_sequence<I2...>> 
  : index_sequence<I1..., (sizeof...(I1)+I2)...> {};

template <size_t N>
struct make_index_sequence
  : _merge_and_renumber<typename make_index_sequence<N/2>::type,
                        typename make_index_sequence<N - N/2>::type> {};

template<> struct make_index_sequence<0> : index_sequence<> {};
template<> struct make_index_sequence<1> : index_sequence<0> {};
9
  • the only error I get from this is the <<< after cout? (gcc 7.2 and clang 4.0 both work for me) Commented Sep 6, 2018 at 23:46
  • actually wait, integer_sequence was added in C++14, are you actually using C++11? Commented Sep 6, 2018 at 23:49
  • live examples: gcc-5.2 and clang 3.5 Commented Sep 6, 2018 at 23:52
  • 1
    this one looks right Commented Sep 7, 2018 at 0:00
  • 1
    Right, but they are still different types. Templates type matching doesn't work like function overload resolution, it has to be an exact match. Commented Sep 7, 2018 at 0:33

1 Answer 1

2

I suggest a zero_sequence completely different: not a struct but a using based over a decltype(), a std::declval() and a only declared helper function (following the std::declval() example.

I mean... if you define the following helper function

template <std::size_t ... Is>
constexpr auto zeHelper (index_sequence<Is...> const &)
   -> decltype( index_sequence<(Is,0u)...>{} );

zero_sequence can be defined as

template <typename T>
using zero_sequence = decltype(zeHelper(std::declval<T>()));

and you can declate both a0 and b0

A0 a0; 
B0 b0; // now works

and compile without problems also

static_assert( std::is_same<A0, B0>::value, "!" );

I'm perplexed as to why this is happening [...] I don't understand why the two cases are different

The problem with your zero_sequence template struct specialization

template<size_t...I> 
struct zero_sequence<index_sequence<I...>> : index_sequence<(I*0u)...>{};

is that there is also the generic version (unimplemented, but there is)

template<typename> struct zero_sequence;

So when you use a index_sequence as template parameter for zero_sequence, the implemented specialization matches and is selected.

But when you use a make_index_sequence, that inherit from index_sequence and can be converted to a index_sequence but isn't exactly a index_sequence, the specialization doesn't match and the generic (unimplemented) version of zero_sequence is selected.

Passing through a function, the zeHelper() that I propose or something similar, avoids this problem because a make_index_sequence is convertible to a index_sequence.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.