【问题标题】:Why does this template argument deduction fail on GCC but not Clang?为什么这个模板参数推导在 GCC 而不是 Clang 上失败?
【发布时间】:2021-08-14 10:47:24
【问题描述】:

我正在使用带有-std=c++20 的 Clang 和 GCC 主干,以下代码在 Clang 上编译良好,但在 GCC 上编译失败。

#include <cstdint>
#include <climits>
#include <type_traits>
#include <concepts>
#include <immintrin.h>

#define VECTOR_SIZE 32

template <typename T> requires std::is_arithmetic_v<T>
using vec __attribute__((__vector_size__(VECTOR_SIZE))) = T;

template <std::unsigned_integral T>
constexpr vec<T> rotl(vec<T> x, int k)
{
    constexpr auto N = CHAR_BIT * sizeof(T);
    return (x << k) | (x >> (N - k));
}

template <std::unsigned_integral T>
constexpr vec<T> rotr(vec<T> x, int k)
{
    constexpr auto N = CHAR_BIT * sizeof(T);
    return (x >> k) | (x << (N - k));
}

vec<uint32_t> test(vec<uint32_t> x)
{
    return rotr(x, 7);
}

GCC 错误:

x86-64 gcc (trunk) (Editor #1, Compiler #1) C++#1 with x86-64 gcc (trunk)
<source>: In function 'vec<unsigned int> test(vec<unsigned int>)':
<source>:27:20: error: no matching function for call to 'rotr(vec<unsigned int>&, int)'
27 |         return rotr(x, 7);
    |                ~~~~^~~~~~
<source>:19:22: note: candidate: 'template<class T>  requires  unsigned_integral<T> constexpr vec<T> rotr(vec<T>, int)'
19 |     constexpr vec<T> rotr(vec<T> x, int k)
    |                      ^~~~
<source>:19:22: note:   template argument deduction/substitution failed:
<source>:19:22: note: constraints not satisfied
In file included from <source>:3:
/opt/compiler-explorer/gcc-trunk-20210524/include/c++/12.0.0/concepts: In substitution of 'template<class T>  requires  unsigned_integral<T> constexpr vec<T> rotr(vec<T>, int) [with T = __vector(8) unsigned int]':
<source>:27:20:   required from here
/opt/compiler-explorer/gcc-trunk-20210524/include/c++/12.0.0/concepts:102:13:   required for the satisfaction of 'integral<_Tp>' [with _Tp = __vector(8) unsigned int]
/opt/compiler-explorer/gcc-trunk-20210524/include/c++/12.0.0/concepts:108:13:   required for the satisfaction of 'unsigned_integral<T>' [with T = __vector(8) unsigned int]
/opt/compiler-explorer/gcc-trunk-20210524/include/c++/12.0.0/concepts:102:24: note: the expression 'is_integral_v<_Tp> [with _Tp = __vector(8) unsigned int]' evaluated to 'false'
102 |     concept integral = is_integral_v<_Tp>;
    |                        ^~~~~~~~~~~~~~~~~~
ASM generation compiler returned: 1
<source>: In function 'vec<unsigned int> test(vec<unsigned int>)':
<source>:27:20: error: no matching function for call to 'rotr(vec<unsigned int>&, int)'
27 |         return rotr(x, 7);
    |                ~~~~^~~~~~
<source>:19:22: note: candidate: 'template<class T>  requires  unsigned_integral<T> constexpr vec<T> rotr(vec<T>, int)'
19 |     constexpr vec<T> rotr(vec<T> x, int k)
    |                      ^~~~
<source>:19:22: note:   template argument deduction/substitution failed:
<source>:19:22: note: constraints not satisfied
In file included from <source>:3:
/opt/compiler-explorer/gcc-trunk-20210524/include/c++/12.0.0/concepts: In substitution of 'template<class T>  requires  unsigned_integral<T> constexpr vec<T> rotr(vec<T>, int) [with T = __vector(8) unsigned int]':
<source>:27:20:   required from here
/opt/compiler-explorer/gcc-trunk-20210524/include/c++/12.0.0/concepts:102:13:   required for the satisfaction of 'integral<_Tp>' [with _Tp = __vector(8) unsigned int]
/opt/compiler-explorer/gcc-trunk-20210524/include/c++/12.0.0/concepts:108:13:   required for the satisfaction of 'unsigned_integral<T>' [with T = __vector(8) unsigned int]
/opt/compiler-explorer/gcc-trunk-20210524/include/c++/12.0.0/concepts:102:24: note: the expression 'is_integral_v<_Tp> [with _Tp = __vector(8) unsigned int]' evaluated to 'false'
102 |     concept integral = is_integral_v<_Tp>;
    |                        ^~~~~~~~~~~~~~~~~~
Execution build compiler returned: 1

【问题讨论】:

    标签: c++ templates gcc c++20 template-argument-deduction


    【解决方案1】:

    我怀疑它是模板参数推导中的 GCC 错误,由您的别名与向量内在属性结合产生的为:

    因此,没有模板参数扣除的代码本身似乎完全有效,只是 GCC 最终以某种方式扣除了 T = __vector(8) unsigned int,然后 std::unsigned_integral&lt;T&gt; 概念失败,因为 is_integral_v&lt;T&gt; 的计算结果为 false

    我想为了更好的答案来解释为什么会发生这种情况,你需要language-lawyer

    【讨论】:

    • 是的,看起来确实如此。如果 gnu.org 允许我重设密码,我计划将其作为错误提交。
    • 我注意到的另一件事是,如果您将一般的Cont&lt;T&gt; 作为template template,那么这个Clang will fail as well 但同样适用于structstd::vector 的别名两个编译器。所以错误(?)似乎与您定义别名的方式有关。这实际上是我第一次看到有人使用__attribute__((__vector_size__())) 的模板别名。到目前为止,我只见过typedef 没有模板参数的人...
    • @Chris_F 所以实际上我认为您可以通过删除概念、将 VECTOR_SIZE 替换为 32 并完全删除函数的主体以及 rotl 来使您的示例更加简洁。跨度>
    • @Chris_F 完美,我也会跟踪它。我有机会简要地看一下标准,它说别名模板与基础类型一样可扣除。因此问题似乎归结为this。 GCC 无法扣除模板化向量内在函数,而 Clang 成功扣除模板。
    猜你喜欢
    • 1970-01-01
    • 2017-01-27
    • 1970-01-01
    • 2012-02-07
    • 2020-10-27
    • 2019-10-22
    • 2012-09-15
    • 1970-01-01
    • 2019-11-20
    相关资源
    最近更新 更多