2015-11-12 2 views
1

Не можем ли мы сделать что-нибудь подобное?C++ 1z (?) Размер массива времени выполнения как возвращаемое значение

auto f(int n, char *arr[]) -> decltype(char *[n]) /* doesn't work */ { 
    char *tmp[n]; // RSA, the size depends on argc 
    for (int i = 0; i < n; ++i) tmp[i] = arr[i]; 
    return tmp; 
} 

int main(int argc, char *argv[]) { 
    auto arr = f(argc, argv); 
    for (auto e : arr) 
     cout << e << endl; 
} 

Я люблю семантику значений (до тех пор, как мой компилятор может сделать правильную подстановку), особенно, когда я реорганизовать большую функцию в набор небольших утилит.

Редактировать: oops, он не попал в C++ 14 ... (Изменено название с "C++ 14" на "C++ 1z (?)".) Как насчет "Расширения массива TS "? Поддерживает ли это что-то подобное?

+0

C++ 14 не га ve временные размерные массивы. Существуют реализации 'string_view' и' array_view', которые вы могли бы использовать для переноса параметров, но они также не являются стандартными. – chris

+1

Встроенные массивы были заброшены новым языком разработки на C++, потому что они сосут. Вы должны либо использовать 'std :: array', либо' std :: vector' или подобные, чтобы воспользоваться такими замечательными функциями, как возврат массива. –

ответ

2

VLA не допускаются ни в одной версии ISO C++.

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

Мне кажется маловероятным, что возврат VLA будет разрешен любым расширением (или C++ 17, если его VLAs сделает это), поскольку возврат массива (даже не VLA) не имеет смысла.

Синтаксис, указывающий возврат массива по значению, отсутствует. в строке return tmp;, tmp распадается на указатель. Массивы не имеют семантики значений.

+0

Пометка вашего компилятора может помочь, хотя публикация в списке рассылки для вашего компилятора может быть лучшим вариантом для получения окончательного ответа о том, позволяет ли компилятор возвращать VLA –

3

Канонический C++ способ сделать то, что вы хотите сделать, это использовать std::vector (или std::array, если количество элементов известно во время компиляции). C++ не использует VLA, как указано в ответе M.M.

Если символьные указатели, связанные не будут оборванных (например, в вашем argv случае), вы можете сделать это:

std::vector<char*> f(int n, char** arr) 
{ 
    std::vector<char*> tmp; 
    tmp.reserve(n); 
    for (int i = 0; i < n; ++i) 
     tmp.push_back(arr[i]); 
    return tmp; 
} 

Если указатели будут болтаться, то лучше создать std::string объекты:

std::vector<std::string> f(int n, char** arr) 
{ 
    std::vector<std::string> tmp; 
    tmp.reserve(n); 
    for (int i = 0; i < n; ++i) 
     tmp.emplace_back(arr[i]); 
    return tmp; 
} 

(emplace_back является новым для C++ 11. в более старых версиях C++, вы можете просто использовать push_back.)

+0

'vector ' будет более сродни коду OP, который не скопируйте содержимое строки. (Неясно, какая версия удовлетворяет его потребностям, конечно, конечно) –

+0

@MM В моем первоначальном ответе я использовал 'vector ', но я не хотел рисковать какой-либо болтовней, поэтому .... (Конечно, не проблема для' argv ', но в целом.) –

+0

Даже в C, который имеет VLA, вы не можете возвращать массивы из функций (и, в частности, вы не можете возвращать VLA). –