首页 > 解决方案 > 当 `std::make_index_sequence` 和 `std::index_sequence` 用于模板参数默认类型时,g++ 和 clang++ 的不同行为

问题描述

另一个“在 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>{});
 }

我看到 g++ compile where 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.

像往常一样,问题是:谁是对的?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;

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

两个编译器都编译。

标签: c++c++14variadic-templatestemplate-specializationtemplate-argument-deduction

解决方案


这显然是某种 Clang/libc++ 错误:类型std::make_index_sequence<…&gt;不是__make_integer_seq,它是…… std::index_sequence<…&gt;std::vector类型别名(和别名模板)是透明的,尽管它有默认的(分配器)模板参数,但推论一直有效。


推荐阅读