Yo uso g++ 4.6.3, (actualmente paquete por defecto para ubuntu 12.04) con la bandera de c++0x, y me tropiezo a través de este:

template <typename T>
inline T getValue(AnObject&)
{
    static_assert(false , "this function has to be implemented for desired type");
}

con el error de compilación:

static_assertion failed "this function has to be implemented for the desired type"

aunque no puedo llamar a esta función en cualquier lugar pero.

Es un g++ error ? No debería esta función se instanciated sólo si se le llama en algún lugar en el código.

3 Comentarios

  1. 25

    Que es debido a que la condición no depende de alguna manera de los parámetros de la plantilla. Por lo tanto, el compilador puede evaluar incluso antes de crear una instancia de la plantilla, y produce los asociados mensaje de error de compilación si la evaluación de los rendimientos de false.

    En otras palabras, esto no es un error. Aunque muchas de las cosas sólo puede ser activada una vez que una plantilla se crea una instancia, hay otras comprobaciones de validez que un compilador puede realizar incluso antes. Esta es la razón por la que C++ tiene dos fases en la búsqueda del nombre, por ejemplo. El compilador está tratando de ayudarte a encontrar errores que son 100% de probabilidades de ocurrir.

    • Usted puede confirmar que esta función es instanciated aunque me llaman de ningún lugar en el código ? Es que lo que usted dijo ?
    • lástima que, en virtud de VS2010 es compilado realmente bien, me tomó un mal hábito…
    • La función no está instanciado, sólo el static_assert() instrucción se ejecuta.
    • en cuyo caso también es totalmente diferente de la static_assert que Andrei Alexandrescu había propuesto en su libro «el C++ Moderno Diseño».
    • No recuerdo cómo Alexandrescu definido, pero que muy probable. Después de todo, esta es una nueva característica del lenguaje, no sólo una biblioteca. Del mismo modo, si usted escribe una función llamada a foo() en su función de plantilla getValue(), y no de la función foo() existe, el código no compilará, debido a que el compilador sabe que no hay manera de que usted podría crear una instancia de la plantilla de una manera que sería compilar.
    • Así que estoy en la búsqueda de una otra manera de static_assert quieras, pero sólo en la plantilla de instanciation tiempo 🙂
    • a continuación, utilice static_assert(), pero que hacen de la condición de dependiente en algunas argumento de plantilla. Hacer que siempre será el rendimiento false de los argumentos que se va a crear una instancia con (por ejemplo,static_assert(typename is_same<T, type_false>::value), "Error!"), pero no mencionan el argumento de plantilla en la condición. Esto le dice al compilador: «Hey, este es un dependiente de nombre, así que espere hasta la creación de instancias antes de juzgar…»
    • El truco estaba mal 🙂 O… se hizo el trabajo, en el que se genera un error en tiempo de compilación, pero no la que esperaba: fue un error de evaluación de la condición en sí, de modo que la enfermedad nunca llegó evaluados para false, que a su vez significa que el mensaje asociado no se muestra. He actualizado mi comentario.
    • ok, veo, perfecto !
    • Tenga en cuenta que static_assert(sizeof(T) == 0, "Error!") es generalmente traídos como otra solución, pero yo creo el concenso es que este puede fallar «principios», ya que el compilador puede saber el tamaño nunca es menor que 1, sin mirar siquiera T. Sólo para mantener que hay.

  2. 50

    La norma dice que en [temp.res]/8

    No diagnóstico deberá ser emitida por una definición de la plantilla para que una válida la especialización puede ser generado. Si no hay una especialización puede ser generado por una definición de la plantilla, y que la plantilla no está creada, la definición de la plantilla está mal formado, no de diagnóstico necesarios. … [ Nota: Si una plantilla es instanciado, los errores serán diagnosticados de acuerdo con los otros
    las reglas establecidas en esta Norma. Exactamente cuando estos errores son diagnosticados es una cualidad de la cuestión de la ejecución. — nota final ]

    No hay manera posible crear instancias de su plantilla de función que se va a compilar, por lo que la definición de la plantilla está mal formado y por lo que el compilador puede (pero no obligados) a rechazar, incluso si no está instanciado.

    Que podía hacer el trabajo de este tipo:

    template<typename T>
    struct foobar : std::false_type
    { };
    
    template <typename T>
    inline T getValue(AnObject&)
    {
        static_assert( foobar<T>::value , "this function has to be implemented for desired type");
    }

    Ahora el compilador no puede rechazar la función de plantilla de inmediato, porque hasta que se crea una instancia de no saber si habrá una especialización de foobar que ha value == true. Cuando se crea una instancia de la correspondiente especialización de foobar<T> será instanciado y la estática afirmación va a fallar, como se desee.

    • Esta respuesta es increíble. No puedo creer todas las maneras en que la gente inventa para hacer C++ someterse a su voluntad. El lenguaje es simplemente enorme.
    • Hace una plantilla alias hacer el mismo o la introducción de una estructura que se requiere?
    • no se puede especializar un alias de la plantilla, por lo que el compilador sabe de inmediato si es siempre falso, y así no funcionaría.
  3. 3

    Esto es realmente un comentario, pero que requieren de un código de ejemplo.

    El santo estándar de la redacción para static_assert no limita sus efectos a instancias de código.

    Sin embargo, el código

    template <typename T>
    inline T getValue(int&)
    {
        typedef char blah[-1];  //Common C++03 static assert, no special semantics.
    }
    
    int main()
    {}

    también falla al compilar con MinGW g++ 4.7.2, lo que acentúa la pregunta.

    Me pensar la respuesta es que g++ es correcta, y que Visual C++ 11.0, que no produce un error de compilación para esto, está mal, pero me sería difícil para prestar el correspondiente análisis en términos de la Santa Estándar de los versos.

    Una consecuencia práctica de que el compilador diferencia es que en la actualidad no se puede confiar en el comportamiento.

    • +1, no voy a repetir veinte Padre Stroustrup antes de dormir.
    • La definición de la plantilla está mal formado, pero creo que es un «no diagnóstico» requiere de caso, por lo tanto los compiladores están a la derecha.
    • lo siento, olvidé mencionar, Visual C++ también ignora static_assert allí.
    • Ver la cita en mi respuesta, se permite si la plantilla no está instanciado

Dejar respuesta

Please enter your comment!
Please enter your name here