Подтвердить что ты не робот

Какое лучшее объяснение ключевого слова export в стандарте С++ 0x?

Я знаю, что в исходном стандарте С++ 0x появилась функция export.

Но я не могу найти описание или объяснение этой функции. Что он должен делать? Также: какой компилятор поддерживает его?

4b9b3361

Ответ 1

Несмотря на то, что в стандарте С++ нет такого требования, некоторые компиляторы требуют, чтобы все функциональные шаблоны были доступны в каждой единицы перевода, в которой он используется. Фактически для этих компиляторов тела шаблонных функций должны быть доступны в файл заголовка. Повторить: это означает, что эти компиляторы не позволят их определять в файлах без заголовка, таких как .cpp файлы. Чтобы уточнить, в С++ ese это означает, что это:

// ORIGINAL version of xyz.h
template <typename T>
struct xyz
 {
    xyz();
    ~xyz();
 };

НЕ будет удовлетворен этими определениями ctor и dtors:

// ORIGINAL version of xyz.cpp
#include "xyz.h"

template <typename T>
xyz<T>::xyz() {}

template <typename T>
xyz<T>::~xyz() {}

потому что используя его:

// main.cpp
#include "xyz.h"

int main()
 {
    xyz<int> xyzint;

    return 0;
 }

приведет к ошибке. Например, с Comeau С++ вы получите:

C:\export>como xyz.cpp main.cpp
C++'ing xyz.cpp...
Comeau C/C++ 4.3.4.1 (May 29 2004 23:08:11) for MS_WINDOWS_x86
Copyright 1988-2004 Comeau Computing.  All rights reserved.
MODE:non-strict warnings microsoft C++

C++'ing main.cpp...
Comeau C/C++ 4.3.4.1 (May 29 2004 23:08:11) for MS_WINDOWS_x86
Copyright 1988-2004 Comeau Computing.  All rights reserved.
MODE:non-strict warnings microsoft C++

main.obj : error LNK2001: unresolved external symbol xyz<T1>::~xyz<int>() [with T1=int]
main.obj : error LNK2019: unresolved external symbol xyz<T1>::xyz<int>() [with T1=int] referenced in function _main
aout.exe : fatal error LNK1120: 2 unresolved externals

поскольку в xyz.cpp не используется ctor или dtor, поэтому нет никаких экземпляров, которые должны произойти оттуда. К лучшему или худшему, так работают шаблоны.

Один из способов этого - явно запросить экземпляр xyz в этом примере xyz<int>. В результате грубой силы это можно добавить к xyz.cpp, добавив эту строку в конец:

template xyz<int>;

который запрашивает создание (все) xyz<int>. Это не в том месте, потому что это означает, что каждый раз, когда возникает новый тип xyz, необходимо изменить файл реализации xyz.cpp. Менее интрузивным способом избежать этого файла является создание другого:

// xyztir.cpp
#include "xyz.cpp" // .cpp file!!!, not .h file!!

template xyz<int>;

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

Поэтому вместо этого другой способ приблизиться к #include "xyz.cpp" в конец xyz.h:

// xyz.h

// ... previous content of xyz.h ...

#include "xyz.cpp"

Конечно, вы могли бы буквально принести (вырезать и вставить) содержимое xyz.cpp до конца xyz.h, отсюда избавиться от xyz.cpp; это вопрос организации файлов, и в конечном итоге результаты предварительной обработки будут одинаковыми, поскольку тела ctor и dtor будут в заголовке и, следовательно, включены в любой запрос компиляции, так как это будет использовать соответствующий заголовок. В любом случае, это имеет побочный эффект, который теперь каждый шаблон находится в вашем файле заголовка. Это может замедлить компиляцию, и это может привести к раздуванию кода. Один из способов приблизиться к последнему - объявить соответствующие функции, в этом случае ctor и dtor, как inline, поэтому для этого вам потребуется изменить xyz.cpp в примере выполнения.

В стороне некоторые компиляторы также требуют, чтобы некоторые функции были определены внутри внутри класса, а не за пределами одного, поэтому в случае этих компиляторов необходимо было бы изменить настройку выше. Обратите внимание, что это проблема компилятора, а не стандарт Standard С++, поэтому не все компиляторы требуют этого. Например, Comeau С++ не делает этого и не должен. Ознакомьтесь с http://www.comeaucomputing.com/4.0/docs/userman/ati.html для получения подробной информации о нашей текущей настройке. Короче говоря, Comeau С++ поддерживает множество моделей, в том числе тот, который близок к тому, что намерения экспорта ключевых слов (как расширение), а также даже поддерживает сам экспорт.

Наконец, обратите внимание, что ключевое слово экспорта С++ предназначено для облегчения первоначального вопроса. Однако в настоящее время Comeau С++ является единственным компилятором, который публикуется для поддержки экспорта. Подробнее см. http://www.comeaucomputing.com/4.0/docs/userman/export.html и http://www.comeaucomputing.com/4.3.0/minor/win95+/43stuff.txt. Надеюсь, что другие компиляторы достигнут соответствия стандарту С++, эта ситуация изменится. В приведенном выше примере использование экспорта означает возврат к исходному коду, который вызвал ошибки компоновщика, и внесение изменений: объявите шаблон в xyz.h с ключевым словом export:

// xyz.h

export
// ... ORIGINAL contents of xyz.h ...

ctor и dtor в xyz.cpp будут экспортироваться просто в силу #includeing xyz.h, который он уже делает. Таким образом, в этом случае вам не нужен xyztir.cpp или запрос на создание экземпляра в конце xyz.cpp, и вам не нужно вводить ctor или dtor вручную в xyz.h. В командной строке, показанной ранее, возможно, что компилятор сделает все это за вас автоматически.

Ответ 2

Смотрите это объяснение для его использования

Многие компиляторы не поддерживают его либо потому, что он слишком новый, либо в случае с gcc - потому что они не одобряют.

Этот пост описывает стандартную поддержку многих компиляторов. Visual Studio поддерживает новые стандарты C/C++?

Ответ 3

Смотрите здесь и здесь для лечения Херб Саттер предмета.

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

Вот почему большинство компиляторов не беспокоятся. Я бы подумал, что они просто удалили экспорт из языка в С++ 0x, но я не думаю, что они это сделали. Может быть, когда-нибудь найдется хороший способ реализовать экспорт, который имеет предназначение.

Ответ 4

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

Комо представил его первым, около 5 лет назад IIRC. Он работал очень хорошо на первой бета-версии, которую я получил. Даже те тесты, как A < 2 > с использованием B < 2 > с использованием A < 1, используя B < 1 > с использованием A < 0 > , работали, если шаблоны A и B были получены из разных TU. Конечно, компоновщик неоднократно вызывал компилятор, но все поиски имен работали нормально. Активация A < 1 > найденные имена из A.cpp, которые были невидимы в B.cpp.

Ответ 5

Проще говоря:

export позволяет отделять объявление (т.е. заголовок) от определения (то есть кода) при написании классов шаблонов. Если export не поддерживается вашим компилятором, вам нужно поместить объявление и определение в одном месте.

Ответ 7

Единственными компиляторами, которые поддерживают экспортированные шаблоны на данный момент (насколько мне известно) являются Comau, тот, который поставляется с Borland С++ Builder X, но не текущий С++ Builder и Intel (по крайней мере, неофициально, если не официально, не уверен).