Как протестировать ctor, принимающий std :: initializer_list с известной длиной во время компиляции? - PullRequest
0 голосов
/ 28 мая 2020

В целях тестирования я хочу вызвать конструктор с простым std::initializer_list. Скажем, значение не имеет значения, а длина, значение и тип известны во время компиляции, например { 42, 42, 42,... N-times }.

Поскольку его конструктор является частным, я попытал счастья с некоторым расширением пакета:

template< int Count, typename ValueType, int Value, int... Values >
struct Generator
    : Generator< Count-1, ValueType, Value, Value, Values... >
{};

template< typename ValueType, int Value, int... Values >
struct Generator< 0, ValueType, Value, Values... >
{
    static constexpr inline std::initializer_list<ValueType>
    get()
    { return { static_cast<ValueType>(Values)... }; }
};

Итак, Generator<3,int,10>::get() дает мне {10,10,10}, да! Но у меня, похоже, есть проблема на время жизни, поскольку initializer_list - это просто прокси-объект, возвращаемый из {..} -выражения внутри функции. Тест не видит ожидаемых значений. Я что-то не замечаю?

struct A {
    A(std::initializer_list<int> l)
    { for(auto i:l) std::cout << i << std::endl; }
};

int main() {
    A a { Generator<3, int, 10>::get() };
    return 0;
}
// prints:
// 32765
// 1762362376
// 32765

Live: https://godbolt.org/z/jYWKB3

1 Ответ

0 голосов
/ 29 мая 2020

Да, это пожизненная проблема. Хотя каждое значение в фигурных скобках известно во время компиляции, initializer_list - это просто прокси, имеющий два указателя (или указатель + размер), и они указывают на мертвую память стека после завершения функции.

I решил это, переместив конструкцию тестируемого программного обеспечения в вариационный шаблон c:

template< typename TestType, int Count, typename ValueType, int Value, int... Values >
struct InitListCtorTest
    : InitListCtorTest< TestType, Count-1, ValueType, Value, Value, Values... >
{};

template< typename TestType, typename ValueType, int Value, int... Values >
struct InitListCtorTest< TestType, 0, ValueType, Value, Values... >
{
    TestType m_testobj { static_cast<ValueType>(Values)... };
};

struct SUT {
    SUT(std::initializer_list<int> l){/*...*/}
};


int main() {
    InitListCtorTest<SUT,3,int,10> gen;
    // Test, if gen.m_testobj has 3 elements with value 10.
    return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...