c++ templates c++11 template-specialization deleted-functions

c++ - La función de plantilla especializada con el caso "general" eliminado no se compila con g++<= 4.8.0 y clang++



templates c++11 (1)

Compilando un proyecto con una versión anterior de g ++ (4.8.0, MinGW) encontré que este código no se compila:

template<typename T> void foo() = delete; template<> void foo<int>(){} int main() { foo<int>(); return 0; }

Parece que g ++ ni siquiera intenta buscar especializaciones explícitas si ve que se borra el caso base.

mitalia@mitalia:~/scratch$ /opt/mingw32-dw2/bin/i686-w64-mingw32-g++ -std=c++11 buggy_deleted_template.cpp buggy_deleted_template.cpp: In function ''int main()'': buggy_deleted_template.cpp:8:14: error: use of deleted function ''void foo() [with T = int]'' foo<int>(); ^ buggy_deleted_template.cpp:5:6: error: declared here void foo<int>(){} ^ mitalia@mitalia:~/scratch$ /opt/mingw32-dw2/bin/i686-w64-mingw32-g++ --version i686-w64-mingw32-g++ (rubenvb-4.8.0) 4.8.0 Copyright (C) 2013 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

En cambio, g ++ 4.8.4 y 5.2 (en Linux) no se quejan. ¿Se trata de un error en la versión anterior del compilador o un área gris en el estándar?

Apéndice

clang 3.4.1 también parece que no le gusta:

mitalia@mitalia:~/scratch$ clang++ -std=c++11 buggy_deleted_template.cpp buggy_deleted_template.cpp:5:6: error: redefinition of ''foo'' void foo<int>(){} ^ buggy_deleted_template.cpp:5:6: note: previous definition is here buggy_deleted_template.cpp:8:5: error: no matching function for call to ''foo'' foo<int>(); ^~~~~~~~ buggy_deleted_template.cpp:2:6: note: candidate template ignored: substitution failure [with T = int] void foo() = delete; ^ 2 errors generated. mitalia@mitalia:~/scratch$ clang++ --version Ubuntu clang version 3.4-1ubuntu3 (tags/RELEASE_34/final) (based on LLVM 3.4) Target: x86_64-pc-linux-gnu Thread model: posix

(y @Baum mit Augen en los comentarios informa que aún no funciona en 3.7)


No sé si lo siguiente será esclarecedor, pero encontré el informe de defectos 941: Especialización explícita de la plantilla de función eliminada con estado C ++ 11 que dice lo siguiente (énfasis) :

De acuerdo con el párrafo 1 de 14.7.3 [temp.expl.spec], solo las plantillas de funciones no eliminadas pueden estar explícitamente especializadas. Sin embargo, no parece haber una necesidad imperiosa de esta restricción, y podría ser útil prohibir el uso de especializaciones con instancias implícitas mientras se permite el uso de versiones explícitamente especializadas.

Resolución propuesta (febrero, 2010):

Cambie 14.7.3 [temp.expl.spec] párrafo 1 de la siguiente manera:

Una especialización explícita de cualquiera de los siguientes:

no eliminado plantilla de función

plantilla de clase

no eliminado Función miembro de una plantilla de clase.

miembro de datos estáticos de una plantilla de clase

clase miembro de una plantilla de clase

plantilla de clase miembro de una clase o plantilla de clase

no eliminado plantilla de función miembro de una clase o plantilla de clase

puede ser declarado ...

Ahora el estado actual del borrador del estándar N4527 es 14.7.3 Especialización explícita [temp.expl.spec]:

1 Una especialización explícita de cualquiera de los siguientes:

(1.1) - plantilla de función

(1.2) - plantilla de clase

(1.3) - plantilla variable

(1.4) - Función miembro de una plantilla de clase.

(1.5) - miembro de datos estáticos de una plantilla de clase

(1.6) - clase miembro de una plantilla de clase

(1.7) - enumeración de miembros de una plantilla de clase

(1.8) - plantilla de clase miembro de una clase o plantilla de clase

(1.9) - plantilla de función miembro de una clase o plantilla de clase

...

Así que supongo:

template<typename T> void foo() = delete; template<> void foo<int>(){} int main() { foo<int>(); return 0; }

Es un código compatible con C ++ 11 y debe ser aceptado.