未定义的类模板成员函数的引用

时间:2022-08-21 22:52:54

I want to use iterators in template class method. Here is my code: (testclass.h)

我想在模板类方法中使用迭代器。这是我的代码:(testclass.h)

template<typename T, typename container>
class TestClassX
{
public:
    void gen(typename container::iterator first );
};

and file testclass.cpp:

和文件testclass.cpp:

template<typename T, typename container>
void TestClassX<T, container>::gen(typename container::iterator first)
{

}

When i try to run it:

当我尝试运行它时:

TestClassX<unsigned, std::vector<unsigned> > testx;
testx.gen(it);

I get an error:

我收到一个错误:

Error:undefined reference to `TestClassX<unsigned int, std::vector<unsigned int, std::allocator<unsigned int> > >::gen(__gnu_cxx::__normal_iterator<unsigned int*, std::vector<unsigned int, std::allocator<unsigned int> > >)'

I use mingw32 4.4

我用的是mingw32 4.4

I want to have a class that can write to different containers like std::vector, std::list, QVector or QList all that have STL-style iterators.

我希望有一个类可以写入不同的容器,如std :: vector,std :: list,QVector或QList,它们都有STL样式的迭代器。

3 个解决方案

#1


10  

Template class methods must be defined in the header file. When you use a template class, the compiler actually compiles a version of that class for the given template parameters. Therefore, it is a requirement that the body of each method is available when including the header file.

必须在头文件中定义模板类方法。当您使用模板类时,编译器实际上为给定的模板参数编译该类的版本。因此,要求在包括头文件时每种方法的主体都可用。

Remove you source file and include the body in testclass.h:

删除源文件并将主体包含在testclass.h中:

template<typename T, typename container>
class TestClassX
{
public:
    void gen(typename container::iterator first ) {

    }
};

#2


1  

Template class methods NEED NOT be defined in the header files. But if you do this you need to define a separate compilation unit (for example templates.cpp) and in that you include the source code file of the template class (eg. #include "container.cpp" // the .cpp NOT the .hpp file) then you need to define the instances of the templates that you are using (eg. template class Container;). You also need to define the object for the template class (eg Link). In this particular case, since we are using a pointer to this object (eg Link*, in Containter ) we merely need to 'forward declare' that object.

模板类方法不需要在头文件中定义。但是如果你这样做,你需要定义一个单独的编译单元(例如templates.cpp),并且你要包含模板类的源代码文件(例如#include“container.cpp”// .cpp not the .hpp文件)然后你需要定义你正在使用的模板的实例(例如模板类Container;)。您还需要为模板类定义对象(例如Link)。在这种特殊情况下,由于我们使用指向此对象的指针(例如Link *,在Containter中),我们只需要'转发声明'该对象。

Here is the full template.cpp file. Which you would compile and link in with the rest of the code.

这是完整的template.cpp文件。您将编译并链接其余代码。

class Link;
#include "Container.cpp"    // use the source code, not the header
template class Container<Link*>; 

I like using this method because it prevents the compiler from generating template class instances automagically and lets you know when it can't find it.

我喜欢使用这种方法,因为它可以防止编译器自动生成模板类实例,并让你知道它什么时候找不到它。

Compile with gcc using the option -fno-implicit-templates.

使用选项-fno-implicit-templates使用gcc进行编译。

When you build everything will be compiled as normal but then the collector will recompile the templates.cpp file for all the objects that use the template.

构建时,所有内容都将按正常方式编译,但收集器将重新编译templates.cpp文件以查找使用该模板的所有对象。

#3


0  

As previously stated, the definition must exist in the same compilation unit when the template is instantiated.

如前所述,当实例化模板时,定义必须存在于同一编译单元中。

I personally prefer to keep the definitions separated from the declarations.
This keeps the header files cleaner and visually separates the interface from the implementation.

我个人更喜欢将定义与声明分开。这样可以使头文件更清晰,并在视觉上将界面与实现分开。

One solution can therefore be as follows:

因此,一种解决方案可以如下:

//TestClass.hpp

//Interface:
template<typename T>
class TestClassX
{
public:
    void gen(int a);
    //more declaraions...
}; 

//Implementations:
template<typename T>
void TestClassX<T>::gen(int a)
{
    //beautiful code
}

You could place the implementation and the interface in separate files (i.e TestClass.hpp and ITestClass.hpp respectively).
TestClass.hpp will initially #include ITestClass.hpp and then define the function as shown in the example above.
The clients will then only need to #include TestClass.hpp.

您可以将实现和接口放在单独的文件中(分别是TestClass.hpp和ITestClass.hpp)。 TestClass.hpp最初将#include ITestClass.hpp,然后定义函数,如上例所示。然后客户端只需#include TestClass.hpp。

#1


10  

Template class methods must be defined in the header file. When you use a template class, the compiler actually compiles a version of that class for the given template parameters. Therefore, it is a requirement that the body of each method is available when including the header file.

必须在头文件中定义模板类方法。当您使用模板类时,编译器实际上为给定的模板参数编译该类的版本。因此,要求在包括头文件时每种方法的主体都可用。

Remove you source file and include the body in testclass.h:

删除源文件并将主体包含在testclass.h中:

template<typename T, typename container>
class TestClassX
{
public:
    void gen(typename container::iterator first ) {

    }
};

#2


1  

Template class methods NEED NOT be defined in the header files. But if you do this you need to define a separate compilation unit (for example templates.cpp) and in that you include the source code file of the template class (eg. #include "container.cpp" // the .cpp NOT the .hpp file) then you need to define the instances of the templates that you are using (eg. template class Container;). You also need to define the object for the template class (eg Link). In this particular case, since we are using a pointer to this object (eg Link*, in Containter ) we merely need to 'forward declare' that object.

模板类方法不需要在头文件中定义。但是如果你这样做,你需要定义一个单独的编译单元(例如templates.cpp),并且你要包含模板类的源代码文件(例如#include“container.cpp”// .cpp not the .hpp文件)然后你需要定义你正在使用的模板的实例(例如模板类Container;)。您还需要为模板类定义对象(例如Link)。在这种特殊情况下,由于我们使用指向此对象的指针(例如Link *,在Containter中),我们只需要'转发声明'该对象。

Here is the full template.cpp file. Which you would compile and link in with the rest of the code.

这是完整的template.cpp文件。您将编译并链接其余代码。

class Link;
#include "Container.cpp"    // use the source code, not the header
template class Container<Link*>; 

I like using this method because it prevents the compiler from generating template class instances automagically and lets you know when it can't find it.

我喜欢使用这种方法,因为它可以防止编译器自动生成模板类实例,并让你知道它什么时候找不到它。

Compile with gcc using the option -fno-implicit-templates.

使用选项-fno-implicit-templates使用gcc进行编译。

When you build everything will be compiled as normal but then the collector will recompile the templates.cpp file for all the objects that use the template.

构建时,所有内容都将按正常方式编译,但收集器将重新编译templates.cpp文件以查找使用该模板的所有对象。

#3


0  

As previously stated, the definition must exist in the same compilation unit when the template is instantiated.

如前所述,当实例化模板时,定义必须存在于同一编译单元中。

I personally prefer to keep the definitions separated from the declarations.
This keeps the header files cleaner and visually separates the interface from the implementation.

我个人更喜欢将定义与声明分开。这样可以使头文件更清晰,并在视觉上将界面与实现分开。

One solution can therefore be as follows:

因此,一种解决方案可以如下:

//TestClass.hpp

//Interface:
template<typename T>
class TestClassX
{
public:
    void gen(int a);
    //more declaraions...
}; 

//Implementations:
template<typename T>
void TestClassX<T>::gen(int a)
{
    //beautiful code
}

You could place the implementation and the interface in separate files (i.e TestClass.hpp and ITestClass.hpp respectively).
TestClass.hpp will initially #include ITestClass.hpp and then define the function as shown in the example above.
The clients will then only need to #include TestClass.hpp.

您可以将实现和接口放在单独的文件中(分别是TestClass.hpp和ITestClass.hpp)。 TestClass.hpp最初将#include ITestClass.hpp,然后定义函数,如上例所示。然后客户端只需#include TestClass.hpp。