10

Another "who's right between g++ and clang++?" question for C++ standard gurus.

Given the following code

#include <utility>

template <std::size_t N, typename = std::make_index_sequence<N>>
struct foo;

template <std::size_t N, std::size_t ... Is>
struct foo<N, std::index_sequence<Is...>>
 { };

template <std::size_t N>
void bar (foo<N> const &)
 { }

int main()
 {
   bar(foo<42u>{});
 }

I see that g++ compile where clang++ gives the following error

tmp_003-14,gcc,clang.cpp:32:4: error: no matching function for call to 'bar'
   bar(foo<42u>{});
   ^~~
tmp_003-14,gcc,clang.cpp:27:6: note: candidate template ignored: could not match
      '__make_integer_seq' against 'integer_sequence'
void bar (foo<N> const &)
     ^
1 error generated.

As usual, the question is: who's right? g++ or clang++?

-- EDIT -- As pointed by HolyBlackCat (thanks!), some older version of clang++ compile this code where the newer don't.

I've tried with Wandbox and I see that clang++ compile from 3.4 (the first version supporting std::make_index_sequence/std::index_sequence) to 3.8.1. Starting from 3.9.1 gives the preceding error.

-- EDIT 2 -- Observe that the clang++ compilation error seems strictly bounded to the use of the first template argument in definition of the default value for the second.

In fact, changing

template <std::size_t N, typename = std::make_index_sequence<N>>
struct foo;

in

// ........................... now doesn't depends from N -->VVV
template <std::size_t N, typename = std::make_index_sequence<10u>>
struct foo;

both compilers compile.

max66
  • 65,235
  • 10
  • 71
  • 111
  • can't reproduce errors with clang: http://coliru.stacked-crooked.com/a/0f579c46cd768466 – Öö Tiib Jul 21 '19 at 12:51
  • @ÖöTiib That's some old clang. It seems that it stopped working since Clang 7. – HolyBlackCat Jul 21 '19 at 12:54
  • Works in recent GCC: https://godbolt.org/z/kXj4I- – wilx Jul 21 '19 at 12:56
  • Then it is likely quality of implementation issue. You should specify versions in question so we can see if there are already open tickets about the issue. – Öö Tiib Jul 21 '19 at 12:58
  • @wilx - works starting from g++ 4.9.0, if I'm not wrong. – max66 Jul 21 '19 at 13:16
  • @ÖöTiib - question edited: according Wandbox, clang++ compile till 3.8.1; gives error from 3.9.1 – max66 Jul 21 '19 at 13:18
  • Hmm ... Clang has to be wrong ... – L. F. Jul 21 '19 at 13:27
  • 2
    `static_assert(std::is_same_v, std::integer_sequence>);` does pass. But it looks like `__make_integer_sequence` is some sort of compiler builtin, which can be used by both [libstdc++](https://code.woboq.org/gcc/libstdc++-v3/include/std/utility.html#296) and [llvm's libc++](https://code.woboq.org/gcc/libstdc++-v3/include/std/utility.html#296). It seems it normally substitutes the correct type, but when there are dependent template arguments, the substitution doesn't happen early enough for template argument deduction. – aschepler Jul 21 '19 at 14:04
  • Barry filed a bug for this at llvm: https://bugs.llvm.org/show_bug.cgi?id=42757 (from https://stackoverflow.com/questions/57206006 , asked just 4 days apart!) – ecatmur Nov 03 '20 at 11:16

1 Answers1

1

This is plainly some sort of Clang/libc++ bug: the type std::make_index_sequence<…> isn’t __make_integer_seq, it’s… std::index_sequence<…>. Type aliases (and alias templates) are transparent, and deduction has always worked for std::vector despite its default (allocator) template argument.

Davis Herring
  • 36,443
  • 4
  • 48
  • 76