LINUX.ORG.RU

[C++][тонкости][я тупой] Нашел нечто в стандарте

 


0

0

1) The potential scope of a name declared in a class consists not only of the declarative region following the name’s declarator, but also of all function bodies, default arguments, and constructor ctor- initializers in that class (including such things in nested classes).

НО!

$cat i.cc
class X {
int f(int t, T r=1234) {return 0; }
typedef long T;

};

int main(void){}
$$ g++ i.cc -pedantic -std=c++98
i.cc:2: error: ‘T’ has not been declared

Понятно и очевидно, что надо просто поменять местами typdef и функцию f. И я так и делал. Но если я правильно понял стандарт, то так тоже должно быть. Еще вот определение name

3 An entity is a value, object, subobject, base class subobject, array element, variable, function, instance of a function, enumerator, type, class member, template, or namespace.

4 A name is a use of an identifier (2.10) that denotes an entity or label (6.6.4, 6.1). A variable is introduced by the declaration of an object. The variable’s name denotes the object.

★★★★★

Последнее исправление: Dudraug (всего исправлений: 2)

Там же написано, 'following the name’s declarator'. Вообще с/c++ обрабатывают языковые конструкции по мере прохода парсера, т.е. сверху вниз, потому иначе просто быть не может. Сначала парсер встречает деньги (т.е. определение типа) и только потом стулья (декларирование).

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

following the name’s declarator

Так ведь.

but also

Вообще с/c++ обрабатывают языковые конструкции по мере прохода парсера, т.е. сверху вниз, потому иначе просто быть не может. Сначала парсер встречает деньги (т.е. определение типа) и только потом стулья (декларирование).

Это я всегда знал и всегда был уверен, что это так. Но это but also меня смутило. Все прочие вещи из этого списка работать будут.

class X
{
   X():d(1){}
   int funct(){ return d;}
   int d;
}

Оно очевидно и понятно для меня, но этот пункт (default arguments) меня все же смущает.

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

В данном случае ничего не сказано о типах, а проблема именно в них. Обьявления типов (или их определение, если на момент использования компилятор обязан знать размер) всегда происходит сверху-вниз. Причины подобного ограничения внутри пространства (в данном случае класс - просто пространство имён) имён те же - в общем случае невозможно разобрать перекрёстные ссылки между типами до их определения.

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

Причины подобного ограничения внутри пространства (в данном случае класс - просто пространство имён) имён те же - в общем случае невозможно разобрать перекрёстные ссылки между типами до их определения.

Если все определения типов находятся внутри одной единицы трансляции - проблем нет, надо только лишний проход по дереву сделать.

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

> Если все определения типов находятся внутри одной единицы трансляции - проблем нет, надо только лишний проход по дереву сделать.

Все типы и так всегда находятся в пределах одной единицы трансляции. Вопрос только в их очерёдности. Уж таков принцип toolchain'а compile+link, что компилятор C/C++ требует определение типа до его использования.

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

Уж таков принцип toolchain'а compile+link, что компилятор C/C++ требует определение типа до его использования.

Компилятор-то требует, не спорю. Но мог бы и не требовать, повторюсь, цена вопроса - лишний проход по дереву.

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

> Но мог бы и не требовать, повторюсь, цена вопроса - лишний проход по дереву.

Согласен, мог бы и не требовать. Тогда язык должен предоставлять альтернативу предварительным #include (ведь их наличие было бы опциональным) и прочим директивам препроцессора, определяющим генерацию типов. Например предварительную трансляцию в байткод. Но тогда это уже был бы не C++.

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

Тогда язык должен предоставлять альтернативу предварительным #include

При чём тут директивы препроцессора? Они же обрабатываются даже до лексического анализа.

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

В данном случае ничего не сказано о типах, а проблема именно в них.

Там и с свойствами ничего не работает. Не придумать мне пример что-то для default arguments для данного куска стандарта.

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

Например предварительную трансляцию в байткод. Но тогда это уже был бы не C++.

1) Почему не с++? Я стандарт не дочитал конечно, но сомневаюсь, что там написано, что компиляция только в натив-код.

2) При чем тут вообще байт-код? Просто двойной парсинг.

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

таков принцип toolchain'а compile+link, что компилятор C/C++ требует определение типа до его использования

А вот здесь тогда как компилирует:

void T(int) {}
int x;

class A {
  int f() {
    T(x);   // declaration of variable x
  }
  typedef int T;
};
?

Вроде получается, что переменная x внутри функции A::f объявлена выше определения типа T, да еще и выглядит это как вызов глобальной функции T c глобальной переменной x в качестве аргумента.

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

Ну тут понятно, тут как и написано в приведенном мною цитате из стандарта. scope type T расширяется и на тело функции f(), как раз тут все верно. Не понятно почему его нельзя использовать в default parametrs , хоты тут это описано. И если там нельзя использовать type, то что тогда можно?

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

Да и правда, походу типа это не касается, во всяком случае для параметров (внутри тел функций-то все видно).

class X
{
	public:
		char f(char  =d);

	static const char d = 'b';
	
};

char  
X::f(char ch)
{
	return ch;
}



int
main(void)
{
	X x;
	std::cout << x.f() << std::endl;
	Sleep(2000);
	return 0;
}

Все, теперь все вроде понятнее. Всем спасибо.

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

Компилятор-то требует, не спорю. Но мог бы и не требовать, повторюсь, цена вопроса - лишний проход по дереву.

class X
{
  typedef int A[sizeof(B)+1];
  typedef int B[sizeof(A)+1];
};

ценой вопроса может быть например топологическая сортировка

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