2017-02-19 7 views
3

Как передать временный массив? Я хочу сделать что-то вроде этого:Как пройти временный массив?

#include <iostream> 

int sum(int arr[]) { 
    int answer = 0; 
    for (const auto& i : arr) { 
     answer += i; 
    } 
    return answer; 
} 

int main() { 
    std::cout << sum({4, 2}) << std::endl;  // error 
    std::cout << sum(int[]{4, 2}) << std::endl; // error 
} 

Требуется ли положительное целое число буквального в фигурных скобках параметра функции в []? Если я включу этот литерал, будет ли он ограничивать, какие массивы я могу передать только массивам такого размера? Кроме того, как я могу передавать элементы массива с помощью ссылки rvalue или ссылки на константу? Поскольку вышеприведенный образец не компилируется, я предполагаю, что параметр параметра функции int&&[] или const int&[] не будет работать.

+1

Вы можете использовать шаблон вывести размер. –

+1

Почему бы не использовать 'std :: array' или' std :: vector'? – Charles

+1

@ c650, я знаю, как их использовать. Я просто хочу узнать о массивах в стиле C. – CodeBricks

ответ

10

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

Собирает все вместе, следующий должен работать

template <std::size_t N> 
int sum(const int (&a)[N]) 
{ 
    int n = 0; 
    for (int i : a) n += i; 
    return n; 
} 

int main() 
{ 
    using X = int[3]; 
    std::cout << sum(X{1, 2, 3}) << "\n"; 
} 

Синтаксический шум может быть обобщены немного с шаблоном псевдонима:

template <std::size_t N> using X = int[N]; 

Использование: sum(X<4>{1, 2, 3, 4}) (Вы не можете иметь параметр шаблона выводится из инициализатора.)

+1

[Демонстрация] (https://ideone.com/VVXJr3). –

+0

В вашем первом фрагменте, как я могу вызвать функцию без объявления псевдонима? – CodeBricks

+0

Этот шаблон шаблона для массивов уже существует: 'std :: array {1, 2, 3}' – zett42

1

Я предлагаю сделать функцию суммы шаблоном, который принимает любой диапазон вместо ограничения его на массивы. Таким образом, вы можете использовать эту функцию со стандартными контейнерами, такими как std :: vector, std :: set или даже пользовательские контейнеры.

Мое решение требует библиотеки boost.range, но кто не использует boost сегодня? Диапазоны даже считаются добавленными в стандартную библиотеку.

#include <iostream> 
#include <array> 
#include <vector> 
#include <string> 
#include <boost/range.hpp> 
#include <initializer_list>  

template< typename Range > 
auto sum_impl(const Range& range) -> typename boost::range_value<Range>::type 
{ 
    typename boost::range_value<Range>::type result{}; 
    for(const auto& elem : range) 
     result += elem; 
    return result; 
} 

template< typename Range > 
auto sum(const Range& range) -> typename boost::range_value<Range>::type 
{ 
    return sum_impl(range); 
} 

template< typename Elem > 
Elem sum(const std::initializer_list<Elem>& range) 
{ 
    return sum_impl(range); 
} 

int main() 
{ 
    // Call the initializer_list overload 
    std::cout << sum({ 1, 2, 3 }) << "\n"; 
    std::cout << sum({ 1.0f, 2.1f, 3.2f }) << "\n"; 

    // Call the generic range overload 
    std::cout << sum(std::array<int,3>{ 1, 2, 3 }) << "\n"; 
    std::cout << sum(std::vector<float>{ 1.0f, 2.1f, 3.2f }) << "\n"; 
    std::cout << sum(std::vector<std::string>{ "a", "b", "c" }) << "\n"; 
} 

Некоторые пояснения:

  • Я использую auto в качестве возвращаемого типа только, чтобы сделать объявление функции более читаемым. Вы также можете написать это:

    typename boost::range_value<Range>::type sum(const Range& range)

  • boost::range_value шаблон используется для вывода типа элементов диапазона. Таким образом, мы можем использовать sum() не только для ints, но и все, что определено operator +=! В моем примере вы можете видеть, что мы можем даже «добавить» (объединить) строки вместе. : D

  • Перегрузка, принимающая параметр std::initializer_list, наконец, делает возможным простой синтаксис, где мы можем позвонить sum({ 1, 2, 3 }) по запросу ОП.Эта перегрузка требуется, так как общая перегрузка не будет выводить initializer_list типа аргумента (см также initializer_list and template type deduction)

Demo:

http://coliru.stacked-crooked.com/a/80393e710fc355a6

Смежные вопросы