Especializaciones de plantillas de clases parciales y SFINAE


He estado usando enfoques basados en SFINAE durante bastante tiempo, especialmente para habilitar/deshabilitar especializaciones de plantillas de clases específicas a través de std::enable_if.

Por lo tanto, me quedé un poco perplejo mientras leía el documento que describe el alias / modismo de detección propuesto void_t:

Http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4502.pdf

La sección 4 está dedicada a la discusión de la validez del idioma, y se refiere a una discusión en la que dos partes discuten sobre aplicabilidad de SFINAE en especializaciones parciales de plantillas de clase (con Richard Smith señalando que el estándar carece de redacción sobre este tema). Hacia el final de la sección, se menciona la siguiente cuestión del GTC

Http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2054

Aquí de nuevo se afirma que el estándar no permite explícitamente el ejemplo reproducido en la edición.

Estoy un poco desconcertado porque me parece que, por ejemplo, la el uso de enable_if en especializaciones parciales ha sido una práctica estándar durante bastante tiempo (vea por ejemplo la documentación de Boost, que menciona explícitamente especializaciones parciales).

¿Estoy malinterpretando los puntos de los documentos anteriores o es realmente una zona gris?

Author: bluescarni, 2015-06-06

1 answers

Me gustaría argumentar que el Estándar no admite SFINAE en especializaciones parciales, debido a un defecto de redacción. Comencemos con [temp.clase.spec.partido]:

Una especialización parcial coincide con una lista de argumentos de plantilla real dada si los argumentos de plantilla de la la especialización parcial se puede deducir de la lista de argumentos de la plantilla actual (14.8.2).

Y, de [temp.deducir], la cláusula SFINAE:

Si una sustitución resulta en un tipo o expresión no válida, la deducción de tipos falla. Un tipo o expresión no válida es uno que estaría mal formado, con un diagnóstico requerido, si se escribe utilizando los argumentos sustituidos. [ Nota: Si no se requiere diagnóstico, el programa todavía está mal formado. La comprobación de acceso se realiza como parte de la sustitución proceso. - end note] Solo los tipos y expresiones no válidos en el contexto inmediato de el tipo de función y sus tipos de parámetros de plantilla pueden resultar en un error de deducción.

El ejemplo ligeramente modificado de CWG es:

template <class T, class U> struct X   {
    typedef char member;
};

template<class T> struct X<T,
     typename enable_if<(sizeof(T)>sizeof(
 float)), float>::type>
{
    typedef long long member;
};

int main() {
    cout << sizeof(X<char, float>::member);
}

La búsqueda de nombres en X encuentra el primario, con T == char, U == float. Nos fijamos en la especialización parcial, y ver si "coincide" - lo que significa que los argumentos de la plantilla "se pueden deducir" - que es decir:

+-------------+--------+-------------------------------------------------+
|             | arg1     arg2                                            |
+-------------+--------+-------------------------------------------------+
| deduce T in | T      | enable_if_t<(sizeof(T) > sizeof(float), float>  |
| from        | char   | float                                           |
+-------------+--------+-------------------------------------------------+

Se aplican las reglas normales de deducción de plantilla. El segundo "argumento" es un contexto no deducible, por lo que deducimos T como char. sizeof(char) > sizeof(float), es false, y enable_if_t<false, float> es un tipo inválido, así que la deducción de tipo debe fallar... pero, el fracaso de la deducción solo puede ocurrir

En el contexto inmediato de el tipo de función y sus tipos de parámetros de plantilla

Y no estamos tratando con un tipo de función o tipos de parámetros de plantilla de función, estamos tratando con tipos de parámetros de plantilla de clase. Una clase no es una función, por lo que la exclusión SFINAE no debe aplicarse si tomamos todo literalmente , y el ejemplo CWG modificado debe conducir a un difícil error.

Sin embargo, el espíritu de la regla parece estar más en la línea de:

Solo los tipos y expresiones no válidos en el contexto inmediato del proceso de deducción pueden resultar en un error de deducción.

No sé cuál sería la razón para excluir específicamente la deducción de especialización parcial de clase. Además, ordenación parcial de especializaciones parciales de plantillas de clase también se parecen a funciones. De [temporal.clase.orden]:

Para dos especializaciones parciales de plantilla de clase, la primera es más especializada que la segunda si, dada la después de reescribir a dos plantillas de función , [...]

El Estándar ya en la siguiente sección exhibe una dualidad entre especializaciones parciales de plantilla de clase y plantillas de función. El hecho de que esto solo se aplica a la ordenación de especialización parcial, y no a la falla de sustitución durante deducción del argumento de especialización, me parece un defecto.


El ejemplo en sí fue X<double, float>. Pero esto en realidad no demuestra o requiere SFINAE, ya que no habría falla de sustitución en ningún lugar.

 14
Author: Barry,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-08 01:56:56