Время компиляции sizeof_array, не используя макрос

MSDN: Поблочное тестирование

основная цель поблочного тестирования состоит в том, чтобы взять самую маленькую часть тестируемого программного обеспечения в приложении, изолировать его от остатка от кода и определить, ведет ли это себя точно, как Вы ожидаете. Каждая единица тестируется отдельно прежде, чем интегрировать их в модули для тестирования интерфейсов между модулями. Поблочное тестирование доказало свое значение в этом, большой процент дефектов определяется во время его использования.

MSDN: Интеграционное тестирование

Интеграционное тестирование является логическим расширением поблочного тестирования. В ее самой простой форме две единицы, которые были уже протестированы, объединены в компонент, и интерфейс между ними тестируется. Компонент, в этом смысле, относится к интегрированному агрегату больше чем одной единицы. В реалистическом сценарии много единиц объединены в компоненты, которые в свою очередь агрегированы в еще большие части программы. Идея состоит в том, чтобы протестировать комбинации частей и в конечном счете развернуть процесс для тестирования модулей с теми из других групп. В конечном счете все модули, составляющие процесс, тестируются вместе. Кроме того, если программа состоит больше чем из одного процесса, они должны быть протестированы в парах, а не внезапно.

сайты Проверки для получения дополнительной информации. Существует много информации там также из источников кроме Microsoft.

16
задан Viktor Sehr 16 May 2017 в 11:19
поделиться

8 ответов

Try the following from 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);
}

It should print out: "The array count is: 10"

22
ответ дан 30 November 2019 в 15:10
поделиться

In C++1x constexpr will get you that:

template <typename T, size_t N>
constexpr size_t countof(T(&)[N])
{
    return N;
}
18
ответ дан 30 November 2019 в 15:10
поделиться

Лучшее, что я могу придумать, это:

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;
}

[EDIT]

Come to think of it, I believe this is provably impossible to do in a single "function-like call" in C++03, apart from macros, and here's why.

On one hand, you will clearly need template parameter deduction to obtain size of array (either directly, or via sizeof as you do). However, template parameter deduction is only applicable to functions, and not to classes; i.e. you can have a template parameter R of type reference-to-array-of-N, where N is another template parameter, but you'll have to provide both R and N at the point of the call; if you want to deduce N from R, only a function call can do that.

On the other hand, the only way any expression involving a function call can be constant is when it's inside sizeof. Anything else (e.g. accessing a static or enum member on return value of function) still requires the function call to occur, which obviously means this won't be a constant expression.

8
ответ дан 30 November 2019 в 15:10
поделиться

Это не совсем то, что вы ищете, но оно близко - фрагмент из 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 () .

«Несовершенный C ++» Мэтью Уилсона В книге также обсуждаются используемые здесь техники.

5
ответ дан 30 November 2019 в 15:10
поделиться

Если вы работаете на платформе только Microsoft, вы можете воспользоваться макросом _countof . Это нестандартное расширение, которое возвращает количество элементов в массиве. Его преимущество перед большинством макросов стиля countof состоит в том, что он вызовет ошибку компиляции, если он используется для типа, не являющегося массивом.

Следующее работает нормально (VS 2008 RTM)

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

Но, опять же, это зависит от MS, поэтому это может не сработать для вас.

4
ответ дан 30 November 2019 в 15:10
поделиться

It appears not to be possible to obtain the sizeof array as a compile-time constant without a macro with current C++ standard (you need a function to deduce the array size, but function calls are not allowed where you need a compile-time constant). [Edit: But see Minaev's brilliant solution!]

However, your template version isn't typesafe either and suffers from the same problem as the macro: it also accepts pointers and notably arrays decayed to a pointer. When it accepts a pointer, the result of sizeof(T*) / sizeof(T) cannot be meaningful.

Better:

template <typename T, size_t N>
size_t sizeof_array(T (&)[N]){
    return N;
}
2
ответ дан 30 November 2019 в 15:10
поделиться

Вы не можете решить эту проблему в целом, это одна из причин использования оберток массивов, таких как boost array (плюс, конечно, поведение в стиле stl).

3
ответ дан 30 November 2019 в 15:10
поделиться

Without C++0x, the closest I can get is:

#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;
}

which either gives you a function you can pass the variable to, or a template you can pass the type too. You can't use the function for a compile time constant, but most cases you know the type, even if only as template parameter.

2
ответ дан 30 November 2019 в 15:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: