Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/133.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ G++;如果模板类构造函数和成员函数的定义与其使用分离,则链接器找不到它们_C++_Templates_Generics_Gcc_Linker - Fatal编程技术网

C++ G++;如果模板类构造函数和成员函数的定义与其使用分离,则链接器找不到它们

C++ G++;如果模板类构造函数和成员函数的定义与其使用分离,则链接器找不到它们,c++,templates,generics,gcc,linker,C++,Templates,Generics,Gcc,Linker,可能重复: 在开发具有某种类型意识的小型解析器时,我遇到了以下难题。简言之: GNU g++“忘记”模板成员函数定义,除非它是在使用它的同一个文件中定义的。 你知道为什么吗 案件档案 为了隔离问题,我将代码精简为三个文件: 头文件Temple.hpp: #ifndef _TEMPLE #define _TEMPLE template <class T> class Temple { private: T deity; public:

可能重复:

在开发具有某种类型意识的小型解析器时,我遇到了以下难题。简言之:

GNU g++“忘记”模板成员函数定义,除非它是在使用它的同一个文件中定义的。

你知道为什么吗

案件档案

为了隔离问题,我将代码精简为三个文件:

头文件Temple.hpp:

#ifndef _TEMPLE
#define _TEMPLE

template <class T> class Temple {
    private:
        T deity;
    public:
        Temple ( T value );
        T see ();
};

#endif
(或者显式命名文件),我在gcc版本4.2.1上遇到一个链接器错误:

/tmp//ccWAFJDF.o(.text+0x24): In function `main':
: undefined reference to `Temple<bool>::Temple(bool)'
/tmp//ccWAFJDF.o(.text+0x2f): In function `main':
: undefined reference to `Temple<bool>::see()'
collect2: ld returned 1 exit status
如果手动将文件Temple.cpp合并到Temple.hpp中,则会获得相同的成功,从而产生:

template <class T> class Temple {
    private:
        T deity;
    public:
        Temple ( T value );
        T see ();
};

template <class T> Temple<T>::Temple ( T value ) : deity( value ) {}
template <class T> T Temple<T>::see () { return deity; }

GNU CC似乎只能记住Temple.cpp中的成员函数定义属于模板类,如果它们在同一个文件中。

在main.c中,在声明类型为
Temple
的变量时,您实例化了该类型。为了实例化模板化类型,您必须能够访问该类型的所有实现

你有两个选择

第一个也是常规的选择是将整个实现放在头文件中,并删除Temple.cpp文件:

// UNTESTED
template <class T> class Temple {
  private:
    T deity;
  public:
    Temple ( T value ) : deity(value) {}
    T see () { return deity; }
};
//未经测试
模板类庙宇{
私人:
T神;
公众:
庙宇(T值):神(值){}
T see(){返回神;}
};
这样,模板的任何用户都可以用他们选择的任何类型实例化它

第二种也是不太传统的方法是在唯一可以访问整个实现的位置显式实例化
Temple
,即Temple.cpp:

#include "Temple.hpp"
template <class T> Temple<T>::Temple ( T value ) : deity( value ) {}
template <class T> T Temple<T>::see () { return deity; }
// temple.cpp
...
// At the very end of the file:
template class Temple<bool>;
//temple.cpp
...
//在文件的最后:
模板类庙宇;

但是,请注意,模板类
Temple
的用户只能使用您创建的实例。在这种情况下,他们只能在main.c中使用
bool

,在声明类型为
Temple
的变量时,您将实例化该类型。为了实例化模板化类型,您必须能够访问该类型的所有实现

你有两个选择

第一个也是常规的选择是将整个实现放在头文件中,并删除Temple.cpp文件:

// UNTESTED
template <class T> class Temple {
  private:
    T deity;
  public:
    Temple ( T value ) : deity(value) {}
    T see () { return deity; }
};
//未经测试
模板类庙宇{
私人:
T神;
公众:
庙宇(T值):神(值){}
T see(){返回神;}
};
这样,模板的任何用户都可以用他们选择的任何类型实例化它

第二种也是不太传统的方法是在唯一可以访问整个实现的位置显式实例化
Temple
,即Temple.cpp:

#include "Temple.hpp"
template <class T> Temple<T>::Temple ( T value ) : deity( value ) {}
template <class T> T Temple<T>::see () { return deity; }
// temple.cpp
...
// At the very end of the file:
template class Temple<bool>;
//temple.cpp
...
//在文件的最后:
模板类庙宇;

但是,请注意,模板类
Temple
的用户只能使用您创建的实例。在这种情况下,它们可能只会使用
bool

如果您没有在类中定义模板函数声明,则应在其前面加上
inline
。否则,您将得到链接器错误。这是相当标准的:@GWW-如果需要内联行为,只应在函数前面加上
inline
。在CPP中使用非内联模板函数是完全可以接受的。只需使用显式实例化。@Rob:对不起,我没有提供足够的上下文。我指的是在头文件中定义它们。那么,这是一个很好的建议。如果你没有在类中定义它们,你应该在模板函数声明前面加上
inline
。否则,您将得到链接器错误。这是相当标准的:@GWW-如果需要内联行为,只应在函数前面加上
inline
。在CPP中使用非内联模板函数是完全可以接受的。只需使用显式实例化。@Rob:对不起,我没有提供足够的上下文。我指的是在头文件中定义它们。那么,这是一个很好的建议。
// UNTESTED
template <class T> class Temple {
  private:
    T deity;
  public:
    Temple ( T value ) : deity(value) {}
    T see () { return deity; }
};
// temple.cpp
...
// At the very end of the file:
template class Temple<bool>;