Are specializations over a non-type template parameter with an argument of different pointer-to-members guaranteed to be unique specializations?

Viewed 80

Consider the following class template:

template <auto>
struct T {};
  • Are two specializations of T, where the respective template-argument is a pointer-to-member(1) to two different but same-type members, guaranteed to refer to different specializations of T?

(1) pointer to data member or pointer to member function.


Or, applied to the following example:

struct S {
    int x;
    int y;
    void f();
    void g();
};

static_assert(std::is_same_v<decltype(&S::x), decltype(&S::y)>);
static_assert(std::is_same_v<decltype(&S::f), decltype(&S::g)>);
  • Are the specializations T<&S::x> and T<&S::y> of T guaranteed to refer to different specializations of T?
  • Are the specializations T<&S::f> and T<&S::g> of T guaranteed to refer to different specializations of T?

or, in code, is the following snippet well-formed?

// T and S as above.
static_assert(!std::is_same_v<T<&S::x>, T<&S::y>>);
static_assert(!std::is_same_v<T<&S::f>, T<&S::g>>);
2 Answers

All standard references below refer to N4659: March 2017 post-Kona working draft/C++17 DIS.


Yes, they are guaranteed to refer to different specializations.

As per [temp.names]/1

[temp.names]/1 A template specialization can be referred to by a template-id: [...]

a template specialization is formally referred to by a template-id, and as per [temp.type]/1, which governs type equivalence, particularly [temp.type]/1.5 [emphasis mine]

[temp.type]/1 Two template-ids refer to the same class, function, or variable if

  • /1.1 their template-names, operator-function-ids, or literal-operator-ids refer to the same template and
  • [...]
  • /1.5 their corresponding non-type template-arguments of pointer-to-member type refer to the same class member or are both the null member pointer value and [...]

does not apply for a template-id if their non-type template-arguments of pointer-to-member type refer to different class members of the same class (template).

For the example of

static_assert(!std::is_same_v<T<&S::x>, T<&S::y>>);
static_assert(!std::is_same_v<T<&S::f>, T<&S::g>>);

particularly, [temp.type]/1.1 applies and is fulfilled, whereas /1.5 applies and is not fulfilled (the remaining paragraphs of [temp.type]/1 does not apply here).

In theory, yes. In reality, consider

union A {
    int foo;
    int bar;
};
template<auto>
struct T{};

MSVC treats T<&A::foo> and T<&A::bar> as the same type.

Related