`template <auto>` and ordering the specialization of a partial class template

Consider:

 #include <type_traits> template <typename> struct Tag {}; template <typename T> auto tag = Tag<T>{}; template <typename...> struct SelectorImpl; // 1 template <auto... xs> struct SelectorImpl<std::integral_constant<decltype(xs), xs>...> {}; // 2 template <typename T, Tag<T>* tag, auto... xs> struct SelectorImpl<std::integral_constant<decltype(tag), tag>, std::integral_constant<decltype(xs), xs>...> {}; template <auto... params> struct Selector : SelectorImpl<std::integral_constant<decltype(params), params>...> {}; int main() { Selector<&tag<int>, 1, 2>{}; } 

Both gcc and clang cannot compile this, saying that the specializations of SelectorImpl ambiguous. I believe that specialization number 2 is more specialized. Am I mistaken? Is this the same problem as here ? This is mistake?

+5
source share
1 answer

First of all, I wanted to make sure that <char X> takes precedence over <auto X> . So I wrote this simple test: https://godbolt.org/g/Hy6NVB

 template<auto...> struct TestSingleImpl; // 1 template<auto x> struct TestSingleImpl<x> { static constexpr bool value = false; }; // 2 template<char x> struct TestSingleImpl<x> { static constexpr bool value = true; }; static_assert(TestSingleImpl<1234>::value == false, "1"); static_assert(TestSingleImpl<'a'>::value == true, "2"); 

Result: yep, takes precedence (no ambiguity)

Then I applied the same example with args variables: https://godbolt.org/g/7mWaeH

 template <typename...> struct Test; // 1 template<auto v, auto... x> struct Test<std::integral_constant<decltype(v), v>, std::integral_constant<decltype(x), x>...> { static constexpr bool value = true; }; // 2 template<char v, auto... x> struct Test<std::integral_constant<char, v>, std::integral_constant<decltype(x), x>...> { static constexpr bool value = false; }; template <auto... params> struct Selector : Test<std::integral_constant<decltype(params), params>...> {}; static_assert(Selector<1234, 1, 2>::value == true, "1"); // 1 - ok static_assert(Selector<'a', 1, 2>::value == false, "2"); // 2 - AMBIGUITY 

Looks like template<char v, auto... x> has no priority over template<auto... x> .

it looks like a HUGE bug in CLANG and GCC

If we remove std::integral_constant , it works correctly: https://godbolt.org/g/grRC8h

This confirms the error :)

 template <auto...> struct Test; // 1 template<auto v, auto... x> struct Test<v, x...> { static constexpr bool value = true; }; // 2 template<char v, auto... x> struct Test<v, x...> { static constexpr bool value = false; }; static_assert(Test<1234, 1, 2>::value == true, "1"); // 1 - ok static_assert(Test<'a', 1, 2>::value == false, "2"); // 2 - ok 
+2
source

Source: https://habr.com/ru/post/1275162/


All Articles