Tentando se especializar com base na validade do tamanho da matriz:
// 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;
}
Problema 1:
O código acima funciona bem com o gcc, mas falha ao compilar com o clang .
Clang gera o erro: redefinição da estrutura do modelo 'absoluta'
Quem está certo?
Edição 2:
Tanto com o gcc como com o clang (se removermos a especialização negativa para trazer o clang de volta ao jogo), não está claro por que absolute<0>()
seleciona o modelo base. Não há nada errado com int[0]
, bem como com std::void_t<int[0]>
o que parece ser mais especializado:
// 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?
}
E ... se o modelo base for declarado apenas sem implementação, como:
// base template
template<int p, typename T = void>
struct absolute;
Ambos gcc e clang deixaria de compilação , queixando-se sobre uso inválido do tipo incompleta para a chamada: absolute<0>()
. Mesmo que pareça se encaixar no caso especializado.
Por que é que?
int[0]
é proibido pelo padrão ISO C ++ timsong-cpp.github.io/cppwp/n4659/dcl.array#1 "seu valor deve ser maior que zero"
template<int p> struct absolute<p, typename std::void_t<int[p]>>
etemplate<int p> struct absolute
isso não é uma duplicata?