Reputation: 29996
I have the following code and I am confused as to why the specialization is not picked.
#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. I am not sure I properly specialized the template but it compiles so I guess it is probably fine.
Upvotes: 1
Views: 63
Reputation: 3871
The code is not well formed and the compiler should report an error. The argument used for a non-type reference template parameter must be (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
An object has internal linkage if it can be referred to from other scopes in the same translation unit and external linkage if it can be referred to from other scopes in both the same translation unit and in other translation units. The template argument arr
is declared in the scope of the main function and only visible within this scope and has thus no linkage and should not match any of the templates.
When I tried it on the compilers installed on my machine clang (6.0.0-1ubuntu2) showed the same behavior as in the question while gcc (7.3.0-16ubuntu3) reported that arr
is a name without linkage. If I move arr
outside function scope (thus giving it external linkage), both compilers accept the code and gives the expected result.
Upvotes: 1