Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> правильная реализация reflection+introspection, в С/С++ путем написания плагина для GCC. 
:(
    Опции темы
xvr
Дата 30.7.2011, 09:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Цитата(boostcoder @  28.7.2011,  22:44 Найти цитируемый пост)
не понял... 

По одной штуке rtti_ex_ на каждый тип

Цитата(boostcoder @  30.7.2011,  09:37 Найти цитируемый пост)
как быть?

Я уже где то писал вверху - таблиц должно быть 2 штуки (точнее 2 набора таблиц) - 1 набор с RTTIEx (rtti_ex_) на каждый тип (извлекаются по уникальному имени, приблизительно таким же, как таблица для обычного RTTI). А вторая таблица - общая для всей программы. В нее складываются имена типов классов и адреса в 1ю таблицу RTTIEx.

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

Вот пример:
Код

class A {
public:
 virtual int func();
};

int A::func() {return int(this);}

int main()
{
 A* a=new A;
 return a->func();
}

Вот результат 
Код

    .file    "rtti.cpp"
    .text
    .align 2
.globl __ZN1A4funcEv
    .def    __ZN1A4funcEv;    .scl    2;    .type    32;    .endef
__ZN1A4funcEv:
LFB2:
    pushl    %ebp
LCFI0:
    movl    %esp, %ebp
LCFI1:
    movl    8(%ebp), %eax
    popl    %ebp
    ret
LFE2:
    .section    .text$_ZN1AC1Ev,"x"
    .linkonce discard
    .align 2
.globl __ZN1AC1Ev
    .def    __ZN1AC1Ev;    .scl    2;    .type    32;    .endef
__ZN1AC1Ev:
LFB6:
    pushl    %ebp
LCFI2:
    movl    %esp, %ebp
LCFI3:
    movl    8(%ebp), %eax
    movl    $__ZTV1A+8, (%eax)
    popl    %ebp
    ret
LFE6:
    .def    ___main;    .scl    2;    .type    32;    .endef
    .text
.globl _main
    .def    _main;    .scl    2;    .type    32;    .endef
_main:
LFB3:
    leal    4(%esp), %ecx
LCFI4:
    andl    $-16, %esp
    pushl    -4(%ecx)
LCFI5:
    pushl    %ebp
LCFI6:
    movl    %esp, %ebp
LCFI7:
    pushl    %ebx
LCFI8:
    pushl    %ecx
LCFI9:
    subl    $32, %esp
LCFI10:
    call    ___main
    movl    $4, (%esp)
    call    __Znwj
    movl    %eax, %ebx
    movl    %ebx, (%esp)
    call    __ZN1AC1Ev
    movl    %ebx, -12(%ebp)
    movl    -12(%ebp), %eax
    movl    (%eax), %eax
    movl    (%eax), %edx
    movl    -12(%ebp), %eax
    movl    %eax, (%esp)
    call    *%edx
    addl    $32, %esp
    popl    %ecx
    popl    %ebx
    popl    %ebp
    leal    -4(%ecx), %esp
    ret
LFE3:
.globl __ZTV1A
    .section    .rdata$_ZTV1A,"dr"
    .linkonce same_size
    .align 8
__ZTV1A:
    .long    0
    .long    __ZTI1A
    .long    __ZN1A4funcEv
.globl __ZTS1A
    .section    .rdata$_ZTS1A,"dr"
    .linkonce same_size
__ZTS1A:
    .ascii "1A\0"
.globl __ZTI1A
    .section    .rdata$_ZTI1A,"dr"
    .linkonce same_size
    .align 4
__ZTI1A:
    .long    __ZTVN10__cxxabiv117__class_type_infoE+8
    .long    __ZTS1A
    .section    .eh_frame,"w"
Lframe1:
    .long    LECIE1-LSCIE1
LSCIE1:
    .long    0x0
    .byte    0x1
    .def    ___gxx_personality_v0;    .scl    2;    .type    32;    .endef
    .ascii "zP\0"
    .uleb128 0x1
    .sleb128 -4
    .byte    0x8
    .uleb128 0x5
    .byte    0x0
    .long    ___gxx_personality_v0
    .byte    0xc
    .uleb128 0x4
    .uleb128 0x4
    .byte    0x88
    .uleb128 0x1
    .align 4
LECIE1:
LSFDE5:
    .long    LEFDE5-LASFDE5
LASFDE5:
    .long    LASFDE5-Lframe1
    .long    LFB3
    .long    LFE3-LFB3
    .uleb128 0x0
    .byte    0x4
    .long    LCFI4-LFB3
    .byte    0xc
    .uleb128 0x1
    .uleb128 0x0
    .byte    0x9
    .uleb128 0x4
    .uleb128 0x1
    .byte    0x4
    .long    LCFI5-LCFI4
    .byte    0xc
    .uleb128 0x4
    .uleb128 0x4
    .byte    0x4
    .long    LCFI6-LCFI5
    .byte    0xe
    .uleb128 0x8
    .byte    0x85
    .uleb128 0x2
    .byte    0x4
    .long    LCFI7-LCFI6
    .byte    0xd
    .uleb128 0x5
    .byte    0x4
    .long    LCFI9-LCFI7
    .byte    0x84
    .uleb128 0x4
    .byte    0x83
    .uleb128 0x3
    .align 4
LEFDE5:
    .def    __Znwj;    .scl    2;    .type    32;    .endef

А вот он же, но с демангленными именами:
Код

    .file    "rtti.cpp"
    .text
    .align 2
.globl A::func()
    .def    A::func();    .scl    2;    .type    32;    .endef
A::func():
LFB2:
    pushl    %ebp
LCFI0:
    movl    %esp, %ebp
LCFI1:
    movl    8(%ebp), %eax
    popl    %ebp
    ret
LFE2:
    .section    .text$_ZN1AC1Ev,"x"
    .linkonce discard
    .align 2
.globl A::A()
    .def    A::A();    .scl    2;    .type    32;    .endef
A::A():
LFB6:
    pushl    %ebp
LCFI2:
    movl    %esp, %ebp
LCFI3:
    movl    8(%ebp), %eax
    movl    vtable for A+8, (%eax)
    popl    %ebp
    ret
LFE6:
    .def    ___main;    .scl    2;    .type    32;    .endef
    .text
.globl _main
    .def    _main;    .scl    2;    .type    32;    .endef
_main:
LFB3:
    leal    4(%esp), %ecx
LCFI4:
    andl    $-16, %esp
    pushl    -4(%ecx)
LCFI5:
    pushl    %ebp
LCFI6:
    movl    %esp, %ebp
LCFI7:
    pushl    %ebx
LCFI8:
    pushl    %ecx
LCFI9:
    subl    $32, %esp
LCFI10:
    call    ___main
    movl    $4, (%esp)
    call    operator new(unsigned int)
    movl    %eax, %ebx
    movl    %ebx, (%esp)
    call    A::A()
    movl    %ebx, -12(%ebp)
    movl    -12(%ebp), %eax
    movl    (%eax), %eax
    movl    (%eax), %edx
    movl    -12(%ebp), %eax
    movl    %eax, (%esp)
    call    *%edx
    addl    $32, %esp
    popl    %ecx
    popl    %ebx
    popl    %ebp
    leal    -4(%ecx), %esp
    ret
LFE3:
.globl vtable for A
    .section    .rdata$_ZTV1A,"dr"
    .linkonce same_size
    .align 8
vtable for A:
    .long    0
    .long    typeinfo for A
    .long    A::func()
.globl typeinfo name for A
    .section    .rdata$_ZTS1A,"dr"
    .linkonce same_size
typeinfo name for A:
    .ascii "1A\0"
.globl typeinfo for A
    .section    .rdata$_ZTI1A,"dr"
    .linkonce same_size
    .align 4
typeinfo for A:
    .long    vtable for __cxxabiv1::__class_type_info+8
    .long    typeinfo name for A
    .section    .eh_frame,"w"
Lframe1:
    .long    LECIE1-LSCIE1
LSCIE1:
    .long    0x0
    .byte    0x1
    .def    ___gxx_personality_v0;    .scl    2;    .type    32;    .endef
    .ascii "zP\0"
    .uleb128 0x1
    .sleb128 -4
    .byte    0x8
    .uleb128 0x5
    .byte    0x0
    .long    ___gxx_personality_v0
    .byte    0xc
    .uleb128 0x4
    .uleb128 0x4
    .byte    0x88
    .uleb128 0x1
    .align 4
LECIE1:
LSFDE5:
    .long    LEFDE5-LASFDE5
LASFDE5:
    .long    LASFDE5-Lframe1
    .long    LFB3
    .long    LFE3-LFB3
    .uleb128 0x0
    .byte    0x4
    .long    LCFI4-LFB3
    .byte    0xc
    .uleb128 0x1
    .uleb128 0x0
    .byte    0x9
    .uleb128 0x4
    .uleb128 0x1
    .byte    0x4
    .long    LCFI5-LCFI4
    .byte    0xc
    .uleb128 0x4
    .uleb128 0x4
    .byte    0x4
    .long    LCFI6-LCFI5
    .byte    0xe
    .uleb128 0x8
    .byte    0x85
    .uleb128 0x2
    .byte    0x4
    .long    LCFI7-LCFI6
    .byte    0xd
    .uleb128 0x5
    .byte    0x4
    .long    LCFI9-LCFI7
    .byte    0x84
    .uleb128 0x4
    .byte    0x83
    .uleb128 0x3
    .align 4
LEFDE5:
    .def    operator new(unsigned int);    .scl    2;    .type    32;    .endef

PM MAIL   Вверх
boostcoder
Дата 30.7.2011, 10:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



Цитата(xvr @  30.7.2011,  09:59 Найти цитируемый пост)
Я уже где то писал вверху - таблиц должно быть 2 штуки (точнее 2 набора таблиц) - 1 набор с RTTIEx (rtti_ex_) на каждый тип (извлекаются по уникальному имени, приблизительно таким же, как таблица для обычного RTTI). А вторая таблица - общая для всей программы. В нее складываются имена типов классов и адреса в 1ю таблицу RTTIEx.

понял!

Цитата(xvr @  30.7.2011,  09:59 Найти цитируемый пост)
Вот пример

буду усваивать.
PM WWW   Вверх
xvr
Дата 30.7.2011, 10:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Строка 81 - таблица RTTI для класса A помещена в отдельную секцию (строка 82,86) с уникальным именем с пометкой для линкера (строка 83,88) оставить только 1 экземпляр этой секции. Причем отдельно размещены имя класса и собственно таблица typeinfo

В строке 93 в специальной секции помещается таблица для обработчика эксепшенов. Линкер соберет все такие секции со всей программы в 1 массив (секцию)

Кстати, мне тут пришла в голову мысль - стриминг данных, базирующийся на интроспекции конечно вещь весьма универсальная, но увы не очень эффективная. Т.к. в процессе работы программы будет по сути происходить интерпретация типов данных. Гораздо более эффективным был бы стримминг, для которого был бы сгенерирован готовый код на этапе трансляции. К сожалению это нельзя сделать универсальным способом, т.к. способ записи/чтения бинарного (или текстового) потока (а так же его структура) сильно зависят от приложения. Да и сам стриминг так же не может быть целиком описан только типами данных. Так что тут напрашивается некий генератор функций/классов для стриминга (видимо по некоторым, заданным пользователем шаблонам).

У меня пока нет ясного видения как это спроектировать  smile 


PM MAIL   Вверх
boostcoder
Дата 30.7.2011, 10:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



xvr, спасибо. разбираюсь smile 
PM WWW   Вверх
boostcoder
Дата 30.7.2011, 10:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



Цитата(xvr @  30.7.2011,  10:11 Найти цитируемый пост)
стриминг данных

что имеется в виду?

PM WWW   Вверх
mes
Дата 30.7.2011, 10:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(boostcoder @  30.7.2011,  09:33 Найти цитируемый пост)
Цитата

стриминг данных
что имеется в виду?

"отправление" данных в поток (stream) , или грубо говоря сериализация.. 




--------------------
PM MAIL WWW   Вверх
boostcoder
Дата 30.7.2011, 10:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



Цитата(mes @  30.7.2011,  10:49 Найти цитируемый пост)
грубо говоря сериализация

после того как разобрался с получением информации, интересна стала не только сериализация(reflection), но и нормальная introspection.
PM WWW   Вверх
mes
Дата 30.7.2011, 11:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(boostcoder @  30.7.2011,  09:57 Найти цитируемый пост)
 не только сериализация(reflection), но и нормальная introspection

стало интересно, что для Вас reflection и introspection ? 


--------------------
PM MAIL WWW   Вверх
boostcoder
Дата 30.7.2011, 19:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



reflection/отражение:
Цитата

В информатике, отражение или рефлексия (синоним интроспекция, англ. reflection) означает процесс, во время которого программа может отслеживать и модифицировать собственную структуру и поведение во время выполнения. Парадигма программирования, положенная в основу отражения, называется рефлексивным программированием. Это один из видов метапрограммирования [1].
В большинстве современных компьютерных архитектур программные инструкции (код) хранятся как данные. Разница между кодом и данными в том, что выполняя код, компьютеры обрабатывают данные. То есть, 'инструкции' 'выполняются', а 'данные' 'обрабатываются' так, как предписано этими инструкциями. Однако, программы, написанные с помощью некоторых языков, способны обрабатывать собственные инструкции как данные и, таким образом, выполнять рефлексивные модификации. Такие самомодифицирующиеся программы в основном создаются с помощью высокоуровневых языков программирования, использующих виртуальные машины (например, Smalltalk, скриптовые языки). Также рефлексия используется в языках с объявляемыми и/или статическими типами (например, Java, Си, ML, Haskell).


introspection:
Цитата

Интроспекция (англ. type introspection) в программировании — возможность в некоторых объектно-ориентированных языках определить тип и структуру объекта во время выполнения программы. Эта возможность особенно заметна в языке Objective C, однако имеется во всех языках, позволяющих манипулировать типами объектов как объектами первого класса. Интроспекция может использоваться для реализации полиморфизма.

вроде как я все правильно понимаю..


да и не в этом суть. xvr меня озадачил ассемблерным кодом и всем сопутствующим...
конечно, если бы кто-то ткнул в ссылку или пример, все было бы сильно проще smile
PM WWW   Вверх
xvr
Дата 30.7.2011, 20:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Цитата(boostcoder @  30.7.2011,  19:36 Найти цитируемый пост)
конечно, если бы кто-то ткнул в ссылку или пример

Чего нет, того нет. Но есть соображение, что структуры данных (таблиц RTTIEx) должны быть по сути сериализованной версией AST (в части описания типов). 
PM MAIL   Вверх
boostcoder
Дата 3.8.2011, 23:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



на идею не забил. просто сейчас по теме больше общаюсь на stackoverflow и в списке рассылке gnu-gcc. вроде как есть надежда понять всю эту магию.
PM WWW   Вверх
boostcoder
Дата 20.8.2011, 11:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



в общем, ковыряниями/тыканиями/читаниями, ничего не получается. доки мало. почти нет.
пришел к решению, дважды обрабатывать единицу трансляции. первый раз - для сбора инфы, второй - для компиляции.
и того, процесс получится таким:
1. запускаем компилятор+плагин для сбора информации.
2. плагин из исходного файла и собранной информации генерит временный файл и завершает компилятор.
3. компилим временный файл как обычно.

вроде все логично...

Добавлено через 1 минуту и 28 секунд
xvr, скажите, а секция данных, может быть любого размера? есть хоть какие-то ограничения?
PM WWW   Вверх
xvr
Дата 20.8.2011, 11:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Цитата(boostcoder @  20.8.2011,  11:27 Найти цитируемый пост)
xvr, скажите, а секция данных, может быть любого размера?

Отдельно взятая секция не может превосходить размера адресного пространства (т.е. 4G на 32bit приложении). Форматы файлов (elf/PE) могут налагать дополнительные ограничения. Но скорее всего гораздо быстрее сломается компилятор/линкер/да и сама программа в run-time. Но в любом случае размеры любых секций до десятков мегабайт должны восприниматься без особых проблем

PM MAIL   Вверх
boostcoder
Дата 20.8.2011, 11:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



Цитата(xvr @  20.8.2011,  11:35 Найти цитируемый пост)
размеры любых секций до десятков мегабайт должны восприниматься без особых проблем

вот и славно.
PM WWW   Вверх
boostcoder
Дата 1.10.2011, 17:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



давайте попытаемся сэмитировать необходимое поведение/реализацию, как будто для этого достаточно только языковых средств.
такой код:
Код

#include <iostream>

namespace reflect {

/***************************************************************************/

enum class type_ {
   char_, uchar_, short_, ushort_, int_, uint_, long_, ulong_,
   int64_, uint64_, array_, pointer_, double_, long_double_, float_,
   class_
};

struct rtti_ex_ {
   const char* name;
   const type_ type;
   const size_t size;
   const size_t align;
   const size_t offset;
};

/***************************************************************************/

struct member_type_ {
   const char* const name;
   const type_ type;
   const size_t size;
   const size_t align;
};

/***************************************************************************/

template<typename... Args>
struct args_pack {
   args_pack(const Args&...) {}
};

/***************************************************************************/

struct member_ {
   member_type_ type() const {}
   const char* name() const {}
   size_t offset() const {}
   
   template<typename... Args>
   void invoke(void* ptr, const args_pack<Args...>& args) {std::cout<<__PRETTY_FUNCTION__<<std::endl;}
   
   void set(const void* ptr) {std::cout<<__PRETTY_FUNCTION__<<std::endl;}
   void get(void* ptr) const {std::cout<<__PRETTY_FUNCTION__<<std::endl;}
};

typedef member_* member_iterator;
typedef const member_* member_const_iterator;

/***************************************************************************/

struct class_ {
   class_(const char* name) {}
   class_(const std::string& name) {}
   
   static void* create(const char* name) {}

   member_const_iterator begin() const {}
   member_const_iterator end() const {}
   member_iterator begin() {}
   member_iterator end() {}
   
   bool contains(const char* name) const {}
   
   member_const_iterator find(const char* name) const {}
   member_iterator find(const char* name) {}

   const member_& nested(size_t idx) const {}
   member_& nested(size_t idx) {}
};

typedef class_* class_iterator;

/***************************************************************************/

class_iterator find(const char* name) {}

/***************************************************************************/

} // namespace reflect

// типа пользовательский код. для симуляции.
// цифры - ID`ы
struct name1 {}; // 0
struct type1 {}; // 1

struct name3 { // 2
   name1 n; // [2, 0]
   type1 t; // [2, 1]
};

struct name2 { // 3
   struct name3 { // [3, 4]
      int a; // [3, 4, 5]
      type1 t; // [3, 4, 1]
   };
   name1 n; // [3, 0]
   type1 t; // [3, 1]
   name3 a;  // [3, 2]
};

// типа сгенеринная таблица.
static const reflect::rtti_ex_
_rtti[] = {
   // name,  type,                   sizeof, allign, offset (?)
   {"name1", reflect::type_::class_, 1,      4,      0},
   {"type1", reflect::type_::class_, 1,      4,      1},
   {"name3", reflect::type_::class_, 2,      4,      2},
   {"name2", reflect::type_::class_, 4,      4,      4}
};

/***************************************************************************/

int main() {
   // получение информации о типе "name1"
   // для этого, перебираем все элементы массива таблиц _rtti
   // тут, к примеру, для получения информации о типе "name2::name3", его имя необходимо указать полностью
   reflect::class_ c1("name1");
   
   // получение информации о типе "name1"
   reflect::class_ c2("name2");
   // поиск декларации типа "name3"
   reflect::member_const_iterator beg = c2.find("name3");
   reflect::member_const_iterator end = c2.end();
   // перечисляем члены "name2::name3"
   while ( ++beg < end ) {
   }
}


http://liveworkspace.org/code/8aae0e0cfb55...28c20b3ceadf96f

начиная с 86ой строки, я пытался сэмитировать поведение.
возникло два вопроса:
1. член offset, структуры rtti_ex_, каково должно быть его значение для типов самого верхнего уровня? т.е. тех, что не являются чьими-то членами.
2. по идее, rtti_ex_, должен содержать массив типов member_type_ ? или же, rtti_ex_ должны ссылаться на другие rtti_ex_, и тип member_type_ вообще лишний?

Добавлено @ 17:55
еще непонятно как быть при декларации данных-членов, и декларации типов-членов, как например "name2::name3"

Добавлено через 13 минут и 2 секунды
по идее, в "enum type_" нужно добавить член decl_, который будет указывать на то, что элемент rtti_ex_ описывает декларацию структуры(или что еще попадает под декларации? typedef?).

Это сообщение отредактировал(а) boostcoder - 1.10.2011, 17:56
PM WWW   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1744 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.