【发布时间】:2019-11-29 16:07:36
【问题描述】:
另一个“在 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++ 编译时 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 开始出现上述错误。
-- EDIT 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;
两个编译器都编译。
【问题讨论】:
-
无法用 clang 重现错误:coliru.stacked-crooked.com/a/0f579c46cd768466
-
@ÖöTiib 那是一些古老的铿锵声。似乎它自 Clang 7 以来就停止了工作。
-
在最近的 GCC 中工作:godbolt.org/z/kXj4I-
-
那么很可能是实施质量问题。您应该指定有问题的版本,以便我们可以查看是否已经有关于该问题的未处理票证。
-
static_assert(std::is_same_v<std::make_integer_sequence<int, 1>, std::integer_sequence<int, 0>>);确实通过了。但看起来__make_integer_sequence是某种内置编译器,libstdc++ 和llvm's libc++ 都可以使用它。看起来它通常会替换正确的类型,但是当有依赖的模板参数时,替换不会足够早地发生模板参数推导。
标签: c++ c++14 variadic-templates template-specialization template-argument-deduction