Создание std :: vector из списка аргументов с использованием шаблонов

0

У меня много кода С#, который я должен написать в C++. У меня нет большого опыта работы в C++.

Я использую Visual Studio 2012 для сборки. Проект представляет собой статическую библиотеку в C++ (не в C++/CLI).

Прошу прощения, если на это уже был дан ответ, но я просто не мог его найти.

В коде С# они инициализируют много массивов, например:

С#

double[] myArray = {10, 20, 30, 40};

Рассматривая, как они используют массивы, при копировании кода на C++ я решил использовать std :: vector для их замены. Я хотел бы иметь возможность инициализировать векторы таким же образом, потому что в Unit Tests они сильно используют инициализацию массивов, но я не могу. Я думаю, что в других версиях C++ вектор поддерживает его, но не в том, что у меня есть.

(Обновление) Чтобы сделать мой предыдущий отчет более ясным:

Это не работает в VS2012:

vector<double> myVector{10, 20, 30, 40};

Из этого вопроса я научился создавать вектор из массива, поэтому теперь у меня есть такая функция:

C++

template<typename T, size_t N>
static std::vector<T> GetVectorFromArray( const T (&array)[N] )
{
    return std::vector<T>(array, array+N);
}

Он отлично работает, но теперь это означает, что я должен создать массив, а затем использовать свою функцию:

C++ (я хотел бы избежать этого, так как UnitTests имеет много массивов.)

double array[] = {1, 3, 5};
vector<double> myVector = ArrayUtils::GetVectorFromArray(array);

Есть ли способ, которым я мог бы заставить мою функцию GetVectorFromArray получить список элементов, которые я мог бы позже преобразовать в вектор? Мой компилятор не поддерживает C++ 11

  • 0
    Ссылка, которую вы упоминаете , специфична для gcc, но вы используете MSVC2012.
  • 0
    Почему вы не используете vector<double> myVector{1, 3, 5} ?
Показать ещё 2 комментария
Теги:
arrays
vector

3 ответа

2
Лучший ответ

Вы не можете иметь "литерал" массивов, кроме тех случаев, когда инициализация массива в объявлении.

По крайней мере, это было до стандарта C++ 11, что позволяет такие вещи, как вы хотите, но с аргументом std::initializer_list:

template<typename T>
static std::vector<T> GetVectorFromArray( std::initializer_list<T> list )
{
    return std::vector<T>(list);
}

С другой стороны, если ваш компилятор поддерживает C++ 11, вы можете использовать его непосредственно с std::vector:

std::vector<int> myVector = { 1, 3, 5 };

Или даже (с равномерной инициализацией)

std::vector<int> myVector{ 1, 3, 5 };

Примечание. К сожалению, VS2012 не поддерживает эти вещи, поэтому вы либо используете временные массивы, либо обновляете компилятор, который его поддерживает (например, VS2013, или GCC, или Clang).


Есть альтернативы. Одна из них - библиотека заданий Boost (как ответил Марк Толонен).

Вы также можете использовать старые аргументы переменной стиля C. См., Например, этот старый вопрос и его принятый ответ, чтобы узнать, как это сделать. Для этого вам нужно либо указать количество элементов в списке аргументов в качестве первого аргумента функции, либо предоставить специальный дозор, чтобы пометить конец списка. Предупреждение: поскольку это унаследовано прямо от C, дополнительной безопасности типа, предоставляемой C++, не существует. Если вы дадите аргумент неправильного типа (например, double или char), вы можете получить неопределенное поведение.

Единственное другое решение состоит в том, чтобы эмулировать, например, библиотеку присвоения Boost, но для этого потребуются нелепые суммы кода.

  • 0
    Я не могу использовать это, но я не могу делать то, что я хочу с любой из предыдущих функций C ++? Мне просто нужна функция, которая получает что-то, например переменные аргументы, а затем я создаю вектор. Я читал, что переменные аргументы это не очень рекомендуется, хотя.
  • 0
    @Dzyann Вы можете прочитать этот старый вопрос и его принятый ответ. Однако для этого требуется, чтобы у вас был часовой, который сообщает, когда заканчивается список чисел, или счетчик, указывающий, сколько элементов в списке в качестве первого аргумента.
Показать ещё 6 комментариев
1

Вы можете моделировать это поведение, используя стороннюю библиотеку C++, Boost:

#include <boost/assign.hpp>
#include <vector>
#include <iostream>

int main()
{
    std::vector<int> v = boost::assign::list_of(1)(2)(3)(4)(5);
    for(auto i : v)
        std::cout << i << std::endl;
}

Вы также можете инициализировать вектор из массива, используя только библиотеку std через non-member begin/end:

#include <boost/assign.hpp>
#include <vector>
#include <iostream>

int main()
{
    int array[] = {1,2,3,4,5,6,7,8,9,10};
    std::vector<int> v(std::begin(array),std::end(array));
    for(auto i : v)
        std::cout << i << std::endl;
}
0

Visual Studio 2012 не поддерживает список инициализаторов. Вы можете использовать VS 2013 для поддержки (или g++)

Ещё вопросы

Сообщество Overcoder
Наверх
Меню