当`std :: make_index_sequence`和`std :: index_sequence`用于模板参数默认类型时,g ++和clang ++的行为不同

max*_*x66 9 c++ template-specialization variadic-templates template-argument-deduction c++14

另一个“谁在g ++和clang ++之间合适?” C ++标准专家的问题。

给出以下代码

#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>{});
 }
Run Code Online (Sandbox Code Playgroud)

我看到g ++编译在clang ++给出以下错误的地方

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.
Run Code Online (Sandbox Code Playgroud)

像往常一样,问题是:谁是对的?g ++还是clang ++?

-编辑-正如HolyBlackCat指出的(谢谢!),一些较旧版本的clang ++会编译此代码,而较新的版本则不会。

我尝试了Wandbox,然后看到clang ++从3.4(支持std::make_index_sequence/ 的第一个版本std::index_sequence)编译为3.8.1。从3.9.1开始会出现上述错误。

-编辑2-观察到clang ++编译错误似乎严格限于在定义第二个模板的默认值时使用第一个模板参数。

实际上,改变

template <std::size_t N, typename = std::make_index_sequence<N>>
struct foo;
Run Code Online (Sandbox Code Playgroud)

// ........................... now doesn't depends from N -->VVV
template <std::size_t N, typename = std::make_index_sequence<10u>>
struct foo;
Run Code Online (Sandbox Code Playgroud)

两个编译器都编译。

Dav*_*ing 1

这显然是某种 Clang/libc++ bug:类型std::make_index_sequence<\xe2\x80\xa6>是 \xe2\x80\x99t __make_integer_seq, it\xe2\x80\x99s\xe2\x80\xa6 std::index_sequence<\xe2\x80\xa6>std::vector类型别名(和别名模板)是透明的,尽管有默认(分配器)模板参数,但推导始终有效。

\n