Como el impulso está prohibido en una empresa para la que trabajo, necesito implementar su funcionalidad en C++ puro. He buscado fuentes de impulso, pero parecen ser demasiado complejas para comprenderlas, al menos para mí. Sé que hay algo llamado static_assert()
en el estándar C++ 0x, pero me gustaría no utilizar ninguna característica C++ 0x.BOOST_STATIC_ASSERT sin impulso
Respuesta
template<bool> struct StaticAssert;
template<> struct StaticAssert<true> {};
int main() {
StaticAssert< (4>3) >(); //OK
StaticAssert< (2+2==5) >(); //ERROR
}
+1 lo suficientemente simple, pero me gusta tener un mensaje asociado con la afirmación –
@Gregory: 'StaticAssert < (2+2==5) > asociadoMensaje();' –
hay lugares donde no desea/no puede usar variables aunque –
Simplemente puede copiar la macro del Boost source file en su propio código. Si no necesita admitir todos los compiladores compatibles con Boost, puede elegir la definición correcta para su compilador y omitir el resto de #ifdef
en ese archivo.
no ignore el error de afirmación. ¿Es eso legal con la licencia de Boost? – gatopeich
Otro truco (que puede ser usado en C) es tratar de construir una matriz con un tamaño negativo si la aserción falle:
#define ASSERT(cond) int foo[(cond) ? 1 : -1]
como un bono, usted puede utilizar un typedef en lugar de una objeto, de modo que sea utilizable en más contextos y no lo hace, tendrá lugar cuando tenga éxito:
#define ASSERT(cond) typedef int foo[(cond) ? 1 : -1]
finalmente, construir un nombre con menos posibilidades de conflicto de nombres (y reutilizables, al menos, en diferentes líneas):
#define CAT_(a, b) a ## b
#define CAT(a, b) CAT_(a, b)
#define ASSERT(cond) typedef int CAT(AsSeRt, __LINE__)[(cond) ? 1 : -1]
¿Podría alguien explicar por qué son necesarias dos macros CAT? ¿Qué problema estás tratando de evitar? Gracias. – grokus
Si no lo hace, los argumentos que son macros (como '__LINE__') no se expanden. Entonces generaría 'AsSeRt__LINE__' en lugar del' AsSeRt42' deseado. Estoy bastante seguro de que hay una pregunta en algún lugar explicando esto en detalle. – AProgrammer
Estoy utilizando el siguiente archivo de cabecera, con el código arrancado de otra persona ...
#ifndef STATIC_ASSERT__H
#define STATIC_ASSERT__H
/* ripped from http://www.pixelbeat.org/programming/gcc/static_assert.html */
#define ASSERT_CONCAT_(a, b) a##b
#define ASSERT_CONCAT(a, b) ASSERT_CONCAT_(a, b)
/* These can't be used after statements in c89. */
#ifdef __COUNTER__
/* microsoft */
#define STATIC_ASSERT(e) enum { ASSERT_CONCAT(static_assert_, __COUNTER__) = 1/(!!(e)) }
#else
/* This can't be used twice on the same line so ensure if using in headers
* that the headers are not included twice (by wrapping in #ifndef...#endif)
* Note it doesn't cause an issue when used on same line of separate modules
* compiled with gcc -combine -fwhole-program. */
#define STATIC_ASSERT(e) enum { ASSERT_CONCAT(assert_line_, __LINE__) = 1/(!!(e)) }
#endif
/* http://msdn.microsoft.com/en-us/library/ms679289(VS.85).aspx */
#ifndef C_ASSERT
#define C_ASSERT(e) STATIC_ASSERT(e)
#endif
#endif
Aquí es mi propia implementación de las afirmaciones estáticas extraídos de mi base de código: Pre-C++11 Static Assertions Without Boost
.
Uso:
STATIC_ASSERT(expression, message);
Cuando falla la prueba de la afirmación estática, se genera un mensaje de error del compilador que de algún modo contiene el STATIC_ASSERTION_FAILED_AT_LINE_xxx_message
.
message
tiene que ser un identificador válido C++, como no_you_cant_have_a_pony
que producirá un error de compilación que contiene:
STATIC_ASSERTION_FAILED_AT_LINE_1337_no_you_cant_have_a_pony
:)
#define CONCATENATE(arg1, arg2) CONCATENATE1(arg1, arg2)
#define CONCATENATE1(arg1, arg2) CONCATENATE2(arg1, arg2)
#define CONCATENATE2(arg1, arg2) arg1##arg2
/**
* Usage:
*
* <code>STATIC_ASSERT(expression, message)</code>
*
* When the static assertion test fails, a compiler error message that somehow
* contains the "STATIC_ASSERTION_FAILED_AT_LINE_xxx_message" is generated.
*
* /!\ message has to be a valid C++ identifier, that is to say it must not
* contain space characters, cannot start with a digit, etc.
*
* STATIC_ASSERT(true, this_message_will_never_be_displayed);
*/
#define STATIC_ASSERT(expression, message)\
struct CONCATENATE(__static_assertion_at_line_, __LINE__)\
{\
implementation::StaticAssertion<static_cast<bool>((expression))> CONCATENATE(CONCATENATE(CONCATENATE(STATIC_ASSERTION_FAILED_AT_LINE_, __LINE__), _), message);\
};\
typedef implementation::StaticAssertionTest<sizeof(CONCATENATE(__static_assertion_at_line_, __LINE__))> CONCATENATE(__static_assertion_test_at_line_, __LINE__)
// note that we wrap the non existing type inside a struct to avoid warning
// messages about unused variables when static assertions are used at function
// scope
// the use of sizeof makes sure the assertion error is not ignored by SFINAE
namespace implementation {
template <bool>
struct StaticAssertion;
template <>
struct StaticAssertion<true>
{
}; // StaticAssertion<true>
template<int i>
struct StaticAssertionTest
{
}; // StaticAssertionTest<int>
} // namespace implementation
STATIC_ASSERT(true, ok);
STATIC_ASSERT(false, ko);
int main()
{
return 0;
}
+1 para "no_you_cant_have_a_pony" –
¡Muy bonito! Esta es una solución completa (y una buena alternativa para la implementación de boost si quieres evitar el impulso) +1 – Samaursa
Creo que esto debería funcionar:
template<bool> struct CompileTimeAssert;
template<> struct CompileTimeAssert<true>{};
#define STATIC_ASSERT(e) (CompileTimeAssert <(e) != 0>())
- 1. ¿Qué es mejor BOOST_MPL_ASSERT o BOOST_STATIC_ASSERT?
- 2. Cómo (cruzado) compilar impulso SIN python?
- 3. impulso :: prueba
- 4. impulso :: :: asio async_write() frente impulso :: asio :: write()
- 5. impulso :: program_options: Cómo especificar un comando sin "-" o "-"
- 6. impulso :: iterador
- 7. impulso shared_ptr
- 8. ¿Hay un impulso :: weak_intrusive_pointer?
- 9. Hilos impulso con CLR
- 10. Cómo discrimina un impulso cancelado de un impulso reactivado deadline_timer
- 11. impulso :: asio UDP difusión
- 12. impulso :: enable_if_c trabajar
- 13. comparar dos impulso :: función
- 14. Propósito del impulso :: checked_desert
- 15. hilo impulso destruye polimorfismo
- 16. impulso cadena MPL
- 17. impulso :: program_options argumento "polimórfica"
- 18. impulso :: shared_ptr contenedor estándar
- 19. impulso shared_ptr y 'esto'
- 20. impulso dinámicamente tamaño asio :: :: búfer
- 21. conversión impulso :: variante para escribir
- 22. idioma booleano seguro en impulso?
- 23. Pobre impulso. Rendimiento de ASIO
- 24. problema de condición de impulso
- 25. ¿Usar bibliotecas de impulso C++?
- 26. impulso serializar y std :: shared_ptr
- 27. Factor de impulso en MultiFieldQueryParser
- 28. presentaciones de impulso simple; ¿Consejo?
- 29. Mejor asio impulso deadline_timer ejemplo
- 30. Sumando dos impulso :: instancias accumulator_set
hicieron preguntas por qué no puedes usar boost –
¿Nadie se tomó el trabajo de construir el caso para que el equipo del abogado diera su aprobación para su uso? – AProgrammer
@Gregory Pakosz, dicen porque es demasiado complejo :) – Konstantin