代码之家  ›  专栏  ›  技术社区  ›  Viktor Sehr

在不使用宏的情况下编译时间sizeof_数组

  •  15
  • Viktor Sehr  · 技术社区  · 15 年前

    这只是困扰我最近几天的事情,我认为这是不可能解决的,但我以前见过模板魔术。

    下面是:

    为了获得标准C++数组中的元素数量,我可以使用宏(1)或类型SeaSeFe内联函数(2):

    (一)

    #define sizeof_array(ARRAY) (sizeof(ARRAY)/sizeof(ARRAY[0]))
    

    (2)

    template <typename T>
    size_t sizeof_array(const T& ARRAY){
        return (sizeof(ARRAY)/sizeof(ARRAY[0]));
    }
    

    如您所见,第一个问题是宏(目前我认为是一个问题),另一个问题是无法在编译时获得数组的大小;即我不能写:

    enum ENUM{N=sizeof_array(ARRAY)};
    

    BOOST_STATIC_ASSERT(sizeof_array(ARRAY)==10);// Assuming the size 10..
    

    有人知道这能否解决吗?

    更新 :

    这个问题是在引入constexpr之前创建的。现在您可以简单地使用:

    template <typename T>
    constexpr auto sizeof_array(const T& iarray) {
        return (sizeof(iarray) / sizeof(iarray[0]));
    }
    
    10 回复  |  直到 8 年前
        1
  •  20
  •   Adisak    15 年前

    here

    template <typename T, size_t N>
    char ( &_ArraySizeHelper( T (&array)[N] ))[N];
    #define mycountof( array ) (sizeof( _ArraySizeHelper( array ) ))
    
    int testarray[10];
    enum { testsize = mycountof(testarray) };
    
    void test() {
        printf("The array count is: %d\n", testsize);
    }
    

        2
  •  15
  •   dalle    15 年前

    constexpr

    template <typename T, size_t N>
    constexpr size_t countof(T(&)[N])
    {
        return N;
    }
    
        3
  •  7
  •   Pavel Minaev    15 年前

    template <class T, std::size_t N>
    char (&sizeof_array(T (&a)[N]))[N];
    
    // As litb noted in comments, you need this overload to handle array rvalues
    // correctly (e.g. when array is a member of a struct returned from function),
    // since they won't bind to non-const reference in the overload above.
    template <class T, std::size_t N>
    char (&sizeof_array(const T (&a)[N]))[N];
    

    sizeof

    int main()
    {
        int a[10];
        int n = sizeof(sizeof_array(a));
        std::cout << n << std::endl;
    }
    

        4
  •  6
  •   Community CDub    8 年前

    Adisak's answer

    template <typename T, size_t N>
    char ( &_ArraySizeHelper( T (&arr)[N] ))[N];
    #define COUNTOF( arr ) (sizeof( _ArraySizeHelper( arr ) ))
    

    _countof macro

    Georg not guaranteed to work with local types for C++03

    void i_am_a_banana() {
      struct { int i; } arr[10];
      std::cout << COUNTOF(arr) << std::endl; // forbidden in C++03
    }
    

    a clever approach

    #define COUNTOF(arr) ( \
       0 * sizeof(reinterpret_cast<const ::Bad_arg_to_COUNTOF*>(arr)) + \
       0 * sizeof(::Bad_arg_to_COUNTOF::check_type((arr), &(arr))) + \
       sizeof(arr) / sizeof((arr)[0]) )
    
    struct Bad_arg_to_COUNTOF {
       class Is_pointer; // incomplete
       class Is_array {};
       template <typename T>
       static Is_pointer check_type(const T*, const T* const*);
       static Is_array check_type(const void*, const void*);
    };
    

    1. arr reinterpret_cast<const T*>
    2. check_type

      Is_pointer

      T T (*)[] SFINAE

        5
  •  5
  •   Michael Burr    15 年前

    winnt.h

    //
    // RtlpNumberOf is a function that takes a reference to an array of N Ts.
    //
    // typedef T array_of_T[N];
    // typedef array_of_T &reference_to_array_of_T;
    //
    // RtlpNumberOf returns a pointer to an array of N chars.
    // We could return a reference instead of a pointer but older compilers do not accept that.
    //
    // typedef char array_of_char[N];
    // typedef array_of_char *pointer_to_array_of_char;
    //
    // sizeof(array_of_char) == N
    // sizeof(*pointer_to_array_of_char) == N
    //
    // pointer_to_array_of_char RtlpNumberOf(reference_to_array_of_T);
    //
    // We never even call RtlpNumberOf, we just take the size of dereferencing its return type.
    // We do not even implement RtlpNumberOf, we just decare it.
    //
    // Attempts to pass pointers instead of arrays to this macro result in compile time errors.
    // That is the point.
    //
    extern "C++" // templates cannot be declared to have 'C' linkage
    template <typename T, size_t N>
    char (*RtlpNumberOf( UNALIGNED T (&)[N] ))[N];
    
    #define RTL_NUMBER_OF_V2(A) (sizeof(*RtlpNumberOf(A)))
    

    RTL_NUMBER_OF_V2() ARRAYSIZE()

    Matthew Wilson's "Imperfect C++"

        6
  •  4
  •   JaredPar    15 年前

    _countof

    static int ARRAY[5];
    enum ENUM{N=_countof(ARRAY)};
    

        7
  •  3
  •   Georg Fritzsche    15 年前
        8
  •  2
  •   UncleBens    15 年前

    template <typename T, size_t N>
    size_t sizeof_array(T (&)[N]){
        return N;
    }
    
        9
  •  2
  •   Pete Kirkham    15 年前

    #include <iostream>
    
    template <typename T>
    struct count_of_type
    {
    };
    
    
    template <typename T, unsigned N>
    struct count_of_type<T[N]> 
    {
        enum { value = N };
    };
    
    template <typename T, unsigned N>
    unsigned count_of ( const T (&) [N] )
    {
        return N;
    };
    
    
    int main ()
    {
        std::cout << count_of_type<int[20]>::value << std::endl;
        std::cout << count_of_type<char[42]>::value << std::endl;
    
        // std::cout << count_of_type<char*>::value << std::endl; // compile error
    
        int foo[1234];
    
        std::cout << count_of(foo) << std::endl;
    
        const char* bar = "wibble";
    
        // std::cout << count_of( bar ) << std::endl; // compile error
    
        enum E1 { N = count_of_type<int[1234]>::value } ;
    
        return 0;
    }
    

        10
  •  0
  •   Hariom Singh    8 年前

    #include <iostream>
    #include <array>
    
    template<class T>
    void test(T t)
    {
        int a[std::tuple_size<T>::value]; // can be used at compile time
        std::cout << std::tuple_size<T>::value << '\n';
    }
    
    int main()
    {
        std::array<float, 3> arr;
        test(arr);
    }