为什么这个模板代码没有 select 偏特化?

Why does this template code does not select partial specialization?

我有以下代码,我很困惑为什么没有选择专业化。

#include<iostream>
using namespace std;
namespace detail {
struct tag {};
}

template<auto& X, typename Y>
struct s{
   static constexpr auto val = 11;
};
template<auto& X>
struct s<X,detail::tag>{
    static constexpr auto val = 22;
};

int main()
{
    static constexpr long long arr[] = {42ll,47ll};
    cout <<  s<arr, detail::tag>::val << endl; //outputs 11, not 22
    cout <<  s<arr, int>::val << endl;
}

P.S。我不确定我是否正确地专门化了模板,但它可以编译,所以我想它可能没问题。

代码格式不正确,编译器应该报错。用于非类型引用模板参数的参数必须是 (C++17 14.3.2)

a constant expression (5.19) that designates the address of a complete object with static storage duration and external or internal linkage or a function with external or internal linkage

如果一个对象可以从同一翻译单元中的其他范围引用,则该对象具有内部链接;如果可以从同一翻译单元和其他翻译单元中的其他范围引用,则该对象具有外部链接。模板参数 arr 在 main 函数的范围内声明,并且仅在该范围内可见,因此没有链接,不应与任何模板匹配。

当我在安装在我机器上的编译器上尝试时,clang (6.0.0-1ubuntu2) 显示出与问题中相同的行为,而 gcc (7.3.0-16ubuntu3) 报告说 arr 是一个没有链接的名称。如果我将 arr 移到函数范围之外(从而为其提供外部链接),两个编译器都会接受代码并给出预期的结果。