Trying to specialize based on validity of array size:
// base template
template<int p, typename T = void>
struct absolute {
operator int () const { return 0; }
};
// positive case template
template<int p>
struct absolute<p, typename std::void_t<int[p]>> {
operator int () const { return p; }
};
// negative case template
template<int p>
struct absolute<p, typename std::void_t<int[-p]>> {
operator int () const { return -p; }
};
int main() {
std::cout << absolute<5>() << std::endl;
std::cout << absolute<-5>() << std::endl;
std::cout << absolute<0>() << std::endl;
}
Issue #1:
Above code works nicely with gcc but fails to compile with clang.
Clang generates the error: redefinition of template struct 'absolute'
Who is right?
Issue #2:
Both with gcc and with clang (if we remove the negative specialization to bring clang back to the game), not clear why absolute<0>()
selects the base template. There is nothing wrong with int[0]
as well as with std::void_t<int[0]>
which seems to be more specialized:
// base template
template<int p, typename T = void>
struct absolute {
operator int () const { return -1; }
};
// positive case template
template<int p>
struct absolute<p, typename std::void_t<int[p]>> {
operator int () const { return p; }
};
int main() {
std::cout << absolute<5>() << std::endl; // 5
std::cout << absolute<0>() << std::endl; // -1, why not 0?
}
And... if the base template is just declared without implementation, as:
// base template
template<int p, typename T = void>
struct absolute;
Both gcc and clang would fail to compile, complaining on invalid use of incomplete type for the call: absolute<0>()
. Even though it seems to fit the specialized case.
Why is that?
>` and `template
struct absolute` isn't that a duplicate?