Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.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++;模板:头文件仍然损坏? 以前使用C++中的模板类,实现必须在头文件中或包含在底部的头文件中。_C++_Templates - Fatal编程技术网

c++;模板:头文件仍然损坏? 以前使用C++中的模板类,实现必须在头文件中或包含在底部的头文件中。

c++;模板:头文件仍然损坏? 以前使用C++中的模板类,实现必须在头文件中或包含在底部的头文件中。,c++,templates,C++,Templates,我已经几年没有使用C++模板了;我刚开始再次使用它们,并观察到这种行为似乎持续存在。还是这样吗?或者编译器是否足够聪明,可以将实现与接口分开?将实现与声明分开,标准强制您使用export关键字。据我所知,只有一个编译器知道如何处理它:Comeau 但是,C++0x将包含一种机制,告诉编译器不要自动实例化某些专门化(外部模板)。因此,如果你想减少编译时间,你可以通过在一个编译单元中显式实例化一些专门化,并在标题中声明为Extru.< /P> < p>你指的是导出的模板(使用导出< /COD>关键字


<>我已经几年没有使用C++模板了;我刚开始再次使用它们,并观察到这种行为似乎持续存在。还是这样吗?或者编译器是否足够聪明,可以将实现与接口分开?

将实现与声明分开,标准强制您使用export关键字。据我所知,只有一个编译器知道如何处理它:Comeau


但是,C++0x将包含一种机制,告诉编译器不要自动实例化某些专门化(外部模板)。因此,如果你想减少编译时间,你可以通过在一个编译单元中显式实例化一些专门化,并在标题中声明为Extru.< /P> < p>你指的是导出的模板(使用<代码>导出< /COD>关键字),这似乎仅由CCOUC++(根据)来支持。
保持接口没有实现代码的一种常见技术是将内联函数定义放入一个单独的“实现”头中,该头可以包含在声明头的末尾。

导出仅由EDG前端支持,据我所知,仅在Comeau编译器中提供

导出并不能消除源代码公开的需要,也不能减少编译依赖性,但它需要编译器构建者付出巨大的努力

因此,赫伯·萨特(Herb Sutter)自己要求编译器构建者“忘记”导出。因为所需的时间投资最好花在其他地方。。。因此,我认为,在其他编译器看到导出花费了多长时间,而且获得的成果很少之后,它们永远不会实现导出

这篇论文名为《为什么我们买不起出口》,上面列出了它,但没有pdf文档(不过谷歌很快就会打开它),现在已经有六年了,我想他们都听了,从来没有想过:)

许多人使用两个头文件(例如
.hpp
.ipp
),一个只包含声明,另一个包含定义,然后只需将一个包含在另一个中

福岛水电站

#ifndef MY_TEMPLATES_HPP
#define MY_TEMPLATES_HPP

template< class T >
void foo(T & t);

#include "foo.ipp"
#endif
\ifndef MY\u模板\u水电站
#定义我的\u模板\u HPP
模板
void foo(T&T);;
#包括“foo.ipp”
#恩迪夫
foo.ipp

#ifdef MY_TEMPLATES_IPP
  nonsense here, that will generate compiler error
#else
#define MY_TEMPLATES_IPP

template< class T >
void foo(T & t) {
   ... // long function
}

#endif
\ifdef我的模板\u IPP
胡说八道,这会产生编译器错误
#否则
#定义我的\u模板\u IPP
模板
空富(T&T){
…//长函数
}
#恩迪夫

当然,这只是获得了一些清晰性,与简单地将所有内容内联到一个头文件相比,没有什么真正的改变。

从技术上讲,它们不需要在头文件中

这种用法的一个例子是,当您有一个具有固定版本集的模板类时(例如,参数sake char和wchar_t)。然后,您可以将所有方法delcaration放入源文件中,并显式实例化这两个版本。这样做的安全性是其他人无法为其不打算使用的类型声明模板

// X.h
template<typename T>
class X
{
     // DECLARATION ONLY OF STUFF
     public:
       X(T const& t);
     private:
       T m_t;
};

// X.cpp
#include "X.h"

// DEFINTION OF STUFF
template<typename T>
X<T>::X(T const& t)
    :m_t(t)
{}

// INSTANCIATE The versions you want.
template class X<char>;
template class X<wchar_t>;


// Main.cpp
#include "X.h"

int main()
{
    X<chat>    x1('a');
    X<wchar_t> x2(L'A');
    // X<int>     x3(5);   // Uncomment for a linker failure.
}
//X.h
模板
X类
{
//只申报物品
公众:
X(T常数&T);
私人:
T m_T;
};
//X.cpp
#包括“X.h”
//物质的定义
模板
X::X(T常数和T)
:m_t(t)
{}
//实例化所需的版本。
模板类X;
模板类X;
//Main.cpp
#包括“X.h”
int main()
{
xx1('a');
X x2(L'A');
//xx3(5);//取消链接器故障的注释。
}
假设人们不能直接包含X.cpp(因为它不是由发行版提供的),那么其他人就不能使用X或X等,但是abovr类已经完全定义


我还见过这种技术用于减少编译时间。因为每个编译单元没有重新生成相同版本的X,所以我们只在一个地方得到定义(因此需要一个编译成本)。缩小到这一点是,您必须手动实例化您使用的每个seprate版本的X。

GCC要经历一个漫长的收集阶段,除非您显式实例化所有模板。VC++似乎可以解决这个问题,但我还是希望避免这一步,如果我知道如何使用模板,这通常是应用程序的情况,而不是库的情况,我会将模板定义放在一个单独的文件中。这也使得代码更具可读性,因为声明中的实现细节不那么凌乱。

即使使用导出,您也无法避免不发布源代码(以任何形式)。EDG文档说:“.et文件仅通知前端导出模板定义的位置;它们实际上并不包含这些定义。因此,包含导出模板定义的源必须在实例化时可用(通常在预链接完成时可用)。特别是,导出机制并不是一种避免以源代码形式发布模板定义的机制。”(我强调)@litb:这太令人恼火了。但谢谢你的回答。我还没有真正实现一个编译器,所以我不能这么说,但我相信EDG的创建者:)它几乎没有“坏”的。这就是语言的定义。通常,您只需在类定义中内联定义成员方法即可解决此问题。@jalf:当必须“解决”某些问题,并且需要一种特殊用途的hack“#include foo.template”时,这是非常糟糕的。抱歉,找到您所指的pdf:,日期为3月2003@MatthieuM:PDF好像坏了。最好是原作:这很漂亮,虽然它不能满足我的需要。不过我会记住的。老实说,我本身并不是在寻找出口。我只是希望标题不必包含模板实现(像其他语言功能一样?)。