Typsicheres count_of( array ) Makro



  • (ungetestet)

    namespace detail
    {
    	template<bool b, std::size_t size>
    	struct count_of_impl;
    
    	template<std::size_t size>
    	struct count_of_impl<true, size>
    	{
    		static const std::size_t value = size;
    	}
    }
    
    #define count_of(array) detail::count_of_impl<boost::is_array<BOOST_TYPEOF(array)>::value, sizeof(array)/sizeof(*array)>::value
    


  • namespace detail {
            template< typename T, size_t N >
            int countof_assert( T ( &array )[ N ] );
        } // namespace detail
    
    #define countof( array ) ( (void)sizeof(detail::countof_assert( array )), sizeof( array ) / sizeof( *array ) )
    


  • Probiers mal so:

    namespace detail {
            template< typename T, size_t N >
            T (&countof_assert(T(&array)[N]))[N]
            {
                return array;
            }
        } // namespace detail
    
    #define countof(array) ( sizeof(detail::countof_assert(array)) / sizeof(*array))
    

    🙂



  • jokester schrieb:

    Probiers mal so:

    namespace detail {
            template< typename T, size_t N >
            T (&countof_assert(T(&array)[N]))[N];
            {
                return array;
            }
        } // namespace detail
    
    #define countof(array) ( sizeof(detail::countof_assert(array)) / sizeof(*array))
    

    🙂

    namespace detail {
            template< typename T, size_t N >
            char (&countof_assert(T(&array)[N]))[N];
        } // namespace detail
    
    #define countof(array) ( sizeof(detail::countof_assert(array)))
    


  • LordJaxom schrieb:

    Manchmal bekommt man aber nunmal ein nacktes Array einfach so vorgesetzt.

    Dann kriegt man es entweder als Pointer + Größenangabe geliefert, so dass die Größe zur Compilezeit nicht zu ermitteln ist.

    Wie auch immer, folgendes ließ sich zumindest auf codepad und MSVC compilieren und liefert das richtige ergebnis:

    template <class T>
    struct count_array;
    
    template <class T, size_t N>
    struct count_array<T [N]>
    {
      char c[N];
    };
    
    template <class T>
    count_array<T> count_(T&);
    
    #define count_of(X) sizeof(count_(X))
    

    Gilt allerdings nur, wenn sizeof beim struct == sizeof char[n]



  • pumuckl schrieb:

    Dann kriegt man es entweder als Pointer + Größenangabe geliefert, so dass die Größe zur Compilezeit nicht zu ermitteln ist.

    Immer diese Grundsatzdiskussionen 😃

    Also gut, im konkreten Fall haben wir viele Strukturen, die COBOL-Datenfelder abbilden. Diese enthalten nur Char-Arrays, Arrays von Char-Arrays oder Arrays von Strukturen, die selbiges enthalten. Da kommt der Bedarf halt ab und zu mal hoch.

    Ansonsten danke für die Lösungen, der sizeof-Trick ist genial 🙂



  • volkard schrieb:

    namespace detail {
            template< typename T, size_t N >
            char (&countof_assert(T(&array)[N]))[N];
        } // namespace detail
    
    #define countof(array) ( sizeof(detail::countof_assert(array)))
    

    me like it 👍



  • LordJaxom schrieb:

    Ansonsten danke für die Lösungen, der sizeof-Trick ist genial 🙂

    sizeof ist sowieso genial. Man kann damit die verrücktesten Dinge tun, zum Beispiel Vererbungshierarchien zur Kompilierzeit zu erkennen... 💡



  • Jo, allgemein finde ich den Trick sizeof(OverloadedFunction(something)) ziemlich cool.



  • Jetzt fällt mir endlich wieder ein wo es beim Template-Trick hakt: der erfordert dass T ein Typ mit "external linkage" ist.
    Also sowas geht damit z.B. nicht:

    void foo()
    {
        struct bar { ... };
        bar b[123];
        countof(b); // bar hat keine "external linkage" -> fehler
    }
    

    Was auch der Grund ist warum ich das in unserer Basis-Library jetzt doch nicht umgeschrieben habe 😞



  • Das kommt in unserem Anwendungsfall zum Glück nicht vor...


Anmelden zum Antworten