Класс шаблона, дающий ошибку компоновщика


У меня есть открытый класс шаблона, в который я добавил метод. Этот класс находится в пространстве имен A. Теперь я вызываю этот метод в другом пространстве имен (скажем, B). Первоначально компилятор выдал мне ошибку компоновщика, говорящую о "неразрешенном внешнем символе" для этого конкретного метода.
Однако, если я вызываю этот метод внутри того же пространства имен (то есть A), он хорошо связывается. После этого он также хорошо связывается в пространстве имен B.
Почему это может происходить?
Это как-то связано с созданием объекта Template моего класса?
Atul
Вот код фрагмент ...

namespace sss  
{  
    namespace AAA  
    {
        template <<typename T, typename TAlloc = Allocator< T > > 
        class DLL_EXPORT A  
        {  
             public:
             // Some other functions that are working fine ...
             bool fooA() const;  
             {  
                  return Size()>0;  
             }  
        };  
    }  
}  


//I get a linker error when I call it in another namespace (say B)...  
//I am accessing this method in public method of some other class in namespace B  

// Including the header for class A ...
#include A.h

namespace QQQ  
{  
    namespace B  
    {  
        class B
        {
            private:  
            AAA::A obj; // Object of class A ...
            public:  
            // SOme methods 
            // Method that calls fooA ...
            GetResult()
            { 
                fooA // This causes causes linker error when i call it here, 
                     // but, it works when i call it in namespace AAA, 
                     // and then it, it works here as well   
            } 
        };

Когда я вызываю этот метод из пространства имен B, он дает неразрешенный внешний символ, но когда я вызываю его из пространства имен A, он хорошо связывается в A, а также в B.
Есть идеи?


person Atul    schedule 03.01.2011    source источник
comment
Можете ли вы предоставить минимальный пример кода, демонстрирующий это?   -  person Oliver Charlesworth    schedule 03.01.2011
comment
Мне просто интересно, что означает пространство имен templaet?   -  person UmmaGumma    schedule 03.01.2011
comment
Я добавил фрагмент кода, спасибо   -  person Atul    schedule 03.01.2011
comment
Но в этом коде нет пространства имен B. Предоставьте фрагмент кода на ideone.com.   -  person Pawel Zubrycki    schedule 03.01.2011
comment
Я снова добавил код, Павел, я новичок в этом STL...   -  person Atul    schedule 04.01.2011


Ответы (3)


Вероятно, это обычная проблема: http://www.parashift.com/c++-faq-lite/templates.html#faq-35.13.

person Oliver Charlesworth    schedule 03.01.2011

Вы неправильно используете шаблонный класс. Следующее должно работать:

namespace QQQ  
{  
    namespace B  
    {
        class B
        {
            // Note the template parameter (int)
            AAA::A<int> obj;

            public:
            bool GetResult() const
            {
                // Note the parentheses and the "obj"
                return obj.fooA()
            } 
        };
    }
}

Единственная проблема, которую я могу себе представить с этим кодом, — это двусмысленность между пространством имен B и классом B, но полный вызов (QQQ::B::B) должен работать.


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

Из-за символа DLL_EXPORT я предполагаю, что вы используете Visual C++. Тем не менее, у ребят из GCC есть хорошее описание, относящееся к Визуальная студия тоже. Большинство библиотек шаблонов, с которыми я знаком (например, Boost), требуют, чтобы все шаблоны были объявлены и определены в заголовочном файле. Также допустимо явно создавать экземпляры шаблонов, как это рекомендовано ребятами из GCC.

person Max Lybbert    schedule 04.01.2011

У меня была такая же проблема с Borland 5 Professional. Я получил ошибку компоновщика с сообщением о внешней ссылке. Решение заключалось в том, чтобы включить файл .cpp в конец вашего заголовка. Потому что компилятору необходимо иметь полное определение, чтобы иметь возможность создать экземпляр шаблона. Следовательно, он должен быть определен в единице перевода, в которой вы хотите его использовать.

Надеюсь, это поможет.

person Jonny Schubert    schedule 05.04.2012