Я знаю, что в исходном стандарте С++ 0x появилась функция export
.
Но я не могу найти описание или объяснение этой функции. Что он должен делать? Также: какой компилятор поддерживает его?
Я знаю, что в исходном стандарте С++ 0x появилась функция export
.
Но я не могу найти описание или объяснение этой функции. Что он должен делать? Также: какой компилятор поддерживает его?
Несмотря на то, что в стандарте С++ нет такого требования, некоторые компиляторы требуют, чтобы все функциональные шаблоны были доступны в каждой единицы перевода, в которой он используется. Фактически для этих компиляторов тела шаблонных функций должны быть доступны в файл заголовка. Повторить: это означает, что эти компиляторы не позволят их определять в файлах без заголовка, таких как .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. В командной строке, показанной ранее, возможно, что компилятор сделает все это за вас автоматически.
Смотрите это объяснение для его использования
Многие компиляторы не поддерживают его либо потому, что он слишком новый, либо в случае с gcc - потому что они не одобряют.
Этот пост описывает стандартную поддержку многих компиляторов. Visual Studio поддерживает новые стандарты C/C++?
Смотрите здесь и здесь для лечения Херб Саттер предмета.
По сути: экспорт был реализован только в одном компиляторе - и в этой реализации экспорт фактически увеличивает связь между определением шаблона и объявлением, тогда как единственной точкой при введении экспорта было уменьшение этой связи.
Вот почему большинство компиляторов не беспокоятся. Я бы подумал, что они просто удалили экспорт из языка в С++ 0x, но я не думаю, что они это сделали. Может быть, когда-нибудь найдется хороший способ реализовать экспорт, который имеет предназначение.
Экспорт - это функция, которая вводит циклическую зависимость между компоновщиком и компилятором. Как отмечали другие, он позволяет одной единицы перевода содержать определение шаблона, используемого в другом. Линкером будет первым, кто обнаружит это, но ему нужен компилятор для создания шаблона. И это связано с реальной тяжелой работой, например, с поиском имен.
Комо представил его первым, около 5 лет назад IIRC. Он работал очень хорошо на первой бета-версии, которую я получил. Даже те тесты, как A < 2 > с использованием B < 2 > с использованием A < 1, используя B < 1 > с использованием A < 0 > , работали, если шаблоны A и B были получены из разных TU. Конечно, компоновщик неоднократно вызывал компилятор, но все поиски имен работали нормально. Активация A < 1 > найденные имена из A.cpp, которые были невидимы в B.cpp.
Проще говоря:
export
позволяет отделять объявление (т.е. заголовок) от определения (то есть кода) при написании классов шаблонов. Если export
не поддерживается вашим компилятором, вам нужно поместить объявление и определение в одном месте.
Стандартные функции, отсутствующие в VС++ 7.1. Часть II: экспорт
Единственными компиляторами, которые поддерживают экспортированные шаблоны на данный момент (насколько мне известно) являются Comau, тот, который поставляется с Borland С++ Builder X, но не текущий С++ Builder и Intel (по крайней мере, неофициально, если не официально, не уверен).