Инстанцируют ли явные экземпляры шаблонов классов C ++ зависимые базовые классы? - PullRequest
12 голосов
/ 14 сентября 2010

Я предполагал, что явный запрос на создание экземпляров автоматически создаст экземпляр всех членов базового класса, но я получаю linker error: unresolved external symbol "public: void Base<int>::foo(int)" при построении этого кода с использованием Visual Studio 2008 или 2010.

Обратите внимание, что добавление вызова к foo() inside bar() заставляет компилятор создавать экземпляр Base<int>::bar(), и сборка завершается успешно, поэтому создается впечатление, что у компилятора есть вся необходимая информация для создания экземпляра foo().

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

Это нормально?Я не смог найти то, что стандарт говорит об этой проблеме.

header.h

template<typename T>
class Base {
public:
    void foo();
};

template<typename T>
class Derived : public Base<T> {
public:
    void bar();
};

source.cpp

#include "header.h"

template<typename T>
void Base<T>::foo() { }

template<typename T>
void Derived<T>::bar() {
    // this->foo();   // adding this forces instantiation of foo()???
}

template class Derived<int>;

main.cpp

#include "header.h"

int main() {
    Derived<int> d;
    d.foo(); // Linker Error: unresolved external symbol "public: void Base<int>::foo(int)"
}

Редактировать:

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

Обратите внимание, что класс определяется с помощью class-head {member-specing} и "Member-спецификация вопределение класса объявляет полный набор членов класса; ни один член не может быть добавлен в другом месте. "Таким образом, члены находятся только между фигурными скобками {}, и открытые члены базового класса не становятся членами производного класса, они просто доступны из производного класса или объектов производного класса.

My onlyОстается вопрос: почему в стандарте указано, что явное создание экземпляра шаблона класса создает только элементы, а не члены базовых классов?Я предполагаю, что это позволяет лучше контролировать то, что и где явно создается.Тот, кто использует явные экземпляры класса шаблона, скорее всего, будет иметь определения базового класса в файле, отличном от определений производного класса, и будет явно создавать каждое из них в отдельности.

1 Ответ

9 голосов
/ 14 сентября 2010

Стандарт гласит

Явное создание экземпляра специализации шаблона класса подразумевает создание всех его членов, ранее явно не специализированных в единице перевода, содержащей явное создание экземпляра.

Другими словами, он не требует, чтобы базовые классы были явно созданы в свою очередь. Это вызовет неявное создание их экземпляров, что не приведет к предварительному созданию определений их членов. В Стандарте есть какая-то уродливая ошибка в отношении того, означает ли какой-либо текст, когда говорится «член», «прямым» или «унаследованным» членом, поскольку это часто кажется «очевидным» для того, кто написал формулировку Стандартов, но не Тот, кто читает это. C ++ 0x добавил некоторые пояснения (он также имеет разницу между явной реализацией объявлений и определений , которых нет в C ++ 03, но даже игнорируя это, C + Формула + 0x содержит еще немного понимания):

Явное создание экземпляра, который называет специализацию шаблона класса, также явное создание экземпляра один и тот же вид (декларация или определение) каждого из его членов (не включая членов, унаследованных от базы классы), который ранее не был явно специализирован на единице перевода, содержащей явное создание экземпляров, за исключением случаев, описанных ниже. [Примечание: кроме того, обычно это будет явное определенные зависящие от реализации данные о классе. - конец примечания]

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...