LINUX.ORG.RU

[C++] почему?

 


0

0
void f(const int[3]);

...

f({1, 2, 3});

почему так нельзя? при том, что вот так:

const int a[3] = {1, 2, 3};

f(a);

вполне себе законно. {} - это, вроде бы, конструктор для const T[]; конструкторы в вызове функции использовать вполне себе можно. основание для такого особого отношения есть вообще?

это всё при том, что:

void g(const char[3]);

...

g("123");

замечательно работает. C-style строка в C++ - она, в общем-то, массив символов - два исключения из общих языковых правил в одном выражении

ну и то, что и в f и в g можно с лёгкостью передавать массивы большего размера, чем указано в сигнатуре, тоже как-то нехорошо. приведение T[] к T* это, конечно, не так уж и плохо - но толку тогда от такой сигнатуры, спрашивается, если компилятор (с -Wall -pedantic) даже предупреждения не выдаёт?

★★★★★
Ответ на: комментарий от LamerOk

>Чего ж тут непонятного? Ты видишь здесь объявление массива?

Не так быстро.... Первоначально речь шла о переменной и о выражении. Теперь ты говоришь об объявлении массива. Что ты подразумеваешь под "объявлением"? Инициализацию (в примере - локальная переменная)? Но я всегда думал, что объявление типа переменной и её инициализацию можно "разнести" (ошибаюсь?).

Ладно, можешь не отвечать: выше уже всё разъяснили...

P.S. Хочешь узнать правду о С++? Не лезь в срач "С++ vs. весь остальной мир" - лезь в "плюсосрач" :):):)

yyk ★★★★★
()
Ответ на: комментарий от yyk

> Что ты подразумеваешь под "объявлением"? Инициализацию (в примере - локальная переменная)?

Как можно перепутать покупку автомобиля с ездой на нем?

> объявление типа переменной и её инициализацию можно "разнести" (ошибаюсь?).


Разумеется можно. Это никак не связанные друг с другом операции.


> Первоначально речь шла о переменной и о выражении.


Она весь тред об этом шла. Я пытался указать на общеизвестный факт - оператор [] в выражении и оператор [] в объявлении переменной имеют разную семантику.

LamerOk ★★★★★
()
Ответ на: комментарий от LamerOk

>Она весь тред об этом шла. Я пытался указать на общеизвестный факт - оператор [] в выражении и оператор [] в объявлении переменной имеют разную семантику.

Аааа, ты опять об этом:

>Тип char[] идентичен типу char* Это разная запись одной и той же семантической конструкции.


Т.е. у одной "семантической конструкции" есть несколько вариантов записей, а одна и та-же "запись" в зависимости от контекста обозначает разные "семантические конструкции"?

И эти люди запрещают мне ковыряться в носу... =)

yyk ★★★★★
()
Ответ на: комментарий от jtootf

правильный вопрос - почему этого нельзя?

Потому что неизвестен тип элементов массива. Это может быть char, int, float - что угодно. Одних фигурных скобочек недостаточно.

Но можно так:

[legolegs@battlehummer ~]$ g++ -x c++ -Wall -Wextra -O - -std=c++0x  && ./a.out
#include <iostream>
using namespace std;
typedef int AR[2][2];
int f(AR arg)
{
return arg[0][0];
}
int main()
{
cout << f(AR{ { 1,2 }, {3,4 } }) << endl;
}
1

legolegs ★★★★★
()
Ответ на: комментарий от legolegs

>Потому что неизвестен тип элементов массива. Это может быть char, int, float - что угодно. Одних фигурных скобочек недостаточно.

мне так и не ответили - чем это отличается от одиночного численного литерала? 1 имеет тип char, int, float?

jtootf ★★★★★
() автор топика
Ответ на: комментарий от jtootf
#include <iostream>
using namespace std;
typedef int arr3[3];
struct struct3
{
  int a1;
  double a2;
  char a3;
};
struct struct4
{
  int a1;
  double a2;
  char a3;
  void *a4;
};

struct A
{
  void m(arr3 arg) {cout << "arr3\n"; }
  void m(struct3 arg) {cout << "struct3\n"; }
  void m(struct4 arg) {cout << "struct4\n"; }
};

int main()
{
  A a;
  arr3 b = {1,2,3};
  struct3 c = {1,2,3};
  a.m( b );
  a.m( c );
  a.m( {1,2,3} ); //что вызвать?
}
legolegs ★★★★★
()
Ответ на: комментарий от legolegs

>a.m( {1,2,3} ); //что вызвать?

это проблема не с типами элементов массива, а с тем, что один и тот же compound literal описывает и гомогенный массив, и гетерогенный кортеж. в противном случае тип массива определялся бы в точности так же, как и тип несоставного численного литерала (либо, что ближе, как тип арифметического выражения с чиленными литералами) - т.е. {1.0, 2, 3}, например, имеет тип double[3]

jtootf ★★★★★
() автор топика
Ответ на: комментарий от jtootf

наверно разработчики языка на то время даже не думали, что такое может понадобится.

alex_custov ★★★★★
()
Ответ на: комментарий от legolegs

>>Потому что неизвестен тип элементов массива.

здрасте, целочисленные литералы без модификаторов - числа int. Тип входного значения в функции у jtootf абсолютно точно известен, автоматический кастинг тоже имеется если понадобится (int -> double, например). Теперь действительно возникает вопрос почему это нельзя. Ответ мне кажется я написал выше, видимо об этом тогда ещё не думали, зато подумали в c++0x. Точно такой же вопрос можно задать по поводу VLA.

alex_custov ★★★★★
()
Ответ на: комментарий от alex_custov

>автоматический кастинг тоже имеется если понадобится (int -> double, например)

кастинг тут работать не будет - т.к. compound literal для массива есть по сути указатель на сегмент данных, а размеры int и double различны (арифметика поломается). однако при совпадении типов (или хотя бы размеров) всё должно работать без проблем

jtootf ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.