即使有显式实例化,也没有为显式专用模板生成代码
No generated code for explicitly specialized template even with explicit instantiation
我从 gcc 4.8.3 和 clang 3.2 得到了一致的行为,但不明白为什么会这样。尽管我有一个 class 模板的显式实例化,但当我使用模板的完全专用实例时,没有生成代码并且我得到一个未定义的符号。
我在文件中有一个简单的 class 模板定义 'temp.hpp'
#pragma once
template <typename T1>
class C
{
public:
C (T1 c) : d_c(c) {};
~C () = default;
void print ();
private:
T1 d_c;
};
请注意方法'print()' 已声明,但未在此处定义。我想要 .cpp 文件中的定义,它将专门针对不同的类型。
所以在 temp.cpp 文件中我有 print() 方法的默认定义
#include "temp.hpp"
#include <iostream>
template<typename T1>
void
C<T1>::print ()
{
std::cout << "Printing: " << d_c << std::endl;
}
后跟 class 类型 'float' 的特化:
template <>
class C <float>
{
public:
C (float f) : d_f(f) {};
~C () = default;
void print ()
{
std::cout << "float: " << d_f << std::endl;
}
private:
float d_f;
};
并且由于定义在 .cpp 文件中,我必须显式实例化我将使用的所有特化。所以我有:
template class C<int>;
template class C<float>;
我的测试驱动程序在 test.cpp 中看起来像这样:
#include "temp.hpp"
int main()
{
int i = 1;
C<int> c_int(i);
float f = 1.2;
C<float> c_float(f);
c_int.print();
c_float.print();
}
编译和链接后出现错误:
test.cpp: undefined reference to `C<float>::print()'
正确生成了 C 的目标代码。我可以使用 nm:
看到它
nm -C temp.o
...
0000000000000000 W C<int>::print()
0000000000000000 W C<int>::C(int)
0000000000000000 W C<int>::C(int)
...
正如我之前提到的,这与 gcc 和 clang 一致,所以我假设这里有一些我不理解的语言规则。
请注意,如果我在文件 temp.cpp 中添加 print() 方法的用法,则会生成代码,但这很愚蠢,在我的真实代码中是不可能的。对于这个简单的测试用例,它看起来像:
void foo ()
{
C<float> s(1.3);
s.print();
}
在激发这个小测试的真实代码中,我的模板有 3 个模板参数,它们结合起来扩展为大约 30 种代码排列。其中一两个我需要做一些不同的专业化,但其他 28 个我可以不理会。
非常感谢任何关于我哪里出错的指示或关于为什么显式实例化不应该生成代码的语言参考。我每天花 1/2 的时间阅读所有其他关于显式实例化的 Whosebug 帖子,并相信我正在正确使用它。
来自[temp.expl.spec]:
If a template, a member template or a member of a class template is explicitly specialized then that specialization
shall be declared before the first use of that specialization that would cause an implicit instantiation
to take place, in every translation unit in which such a use occurs; no diagnostic is required. If the program
does not provide a definition for an explicit specialization and either the specialization is used in a way
that would cause an implicit instantiation to take place or the member is a virtual member function, the
program is ill-formed, no diagnostic required.
我们在 temp.cpp 中明确特化了 C
,但在 test.cpp 中,它在使用前并未声明。因此,您的代码格式错误,不需要诊断。您只需将 C<float>
的声明移动到 temp.hpp
始终注意显式特化。该标准非常重视它们:
The placement of explicit specialization declarations for function templates, class templates, [...], can affect whether a program is well-formed according
to the relative positioning of the explicit specialization declarations and their points of instantiation
in the translation unit as specified above and below. When writing a specialization, be careful about its
location; or to make it compile will be such a trial as to kindle its self-immolation.
我从 gcc 4.8.3 和 clang 3.2 得到了一致的行为,但不明白为什么会这样。尽管我有一个 class 模板的显式实例化,但当我使用模板的完全专用实例时,没有生成代码并且我得到一个未定义的符号。
我在文件中有一个简单的 class 模板定义 'temp.hpp'
#pragma once
template <typename T1>
class C
{
public:
C (T1 c) : d_c(c) {};
~C () = default;
void print ();
private:
T1 d_c;
};
请注意方法'print()' 已声明,但未在此处定义。我想要 .cpp 文件中的定义,它将专门针对不同的类型。
所以在 temp.cpp 文件中我有 print() 方法的默认定义
#include "temp.hpp"
#include <iostream>
template<typename T1>
void
C<T1>::print ()
{
std::cout << "Printing: " << d_c << std::endl;
}
后跟 class 类型 'float' 的特化:
template <>
class C <float>
{
public:
C (float f) : d_f(f) {};
~C () = default;
void print ()
{
std::cout << "float: " << d_f << std::endl;
}
private:
float d_f;
};
并且由于定义在 .cpp 文件中,我必须显式实例化我将使用的所有特化。所以我有:
template class C<int>;
template class C<float>;
我的测试驱动程序在 test.cpp 中看起来像这样:
#include "temp.hpp"
int main()
{
int i = 1;
C<int> c_int(i);
float f = 1.2;
C<float> c_float(f);
c_int.print();
c_float.print();
}
编译和链接后出现错误:
test.cpp: undefined reference to `C<float>::print()'
正确生成了 C
nm -C temp.o
...
0000000000000000 W C<int>::print()
0000000000000000 W C<int>::C(int)
0000000000000000 W C<int>::C(int)
...
正如我之前提到的,这与 gcc 和 clang 一致,所以我假设这里有一些我不理解的语言规则。
请注意,如果我在文件 temp.cpp 中添加 print() 方法的用法,则会生成代码,但这很愚蠢,在我的真实代码中是不可能的。对于这个简单的测试用例,它看起来像:
void foo ()
{
C<float> s(1.3);
s.print();
}
在激发这个小测试的真实代码中,我的模板有 3 个模板参数,它们结合起来扩展为大约 30 种代码排列。其中一两个我需要做一些不同的专业化,但其他 28 个我可以不理会。
非常感谢任何关于我哪里出错的指示或关于为什么显式实例化不应该生成代码的语言参考。我每天花 1/2 的时间阅读所有其他关于显式实例化的 Whosebug 帖子,并相信我正在正确使用它。
来自[temp.expl.spec]:
If a template, a member template or a member of a class template is explicitly specialized then that specialization shall be declared before the first use of that specialization that would cause an implicit instantiation to take place, in every translation unit in which such a use occurs; no diagnostic is required. If the program does not provide a definition for an explicit specialization and either the specialization is used in a way that would cause an implicit instantiation to take place or the member is a virtual member function, the program is ill-formed, no diagnostic required.
我们在 temp.cpp 中明确特化了 C
,但在 test.cpp 中,它在使用前并未声明。因此,您的代码格式错误,不需要诊断。您只需将 C<float>
的声明移动到 temp.hpp
始终注意显式特化。该标准非常重视它们:
The placement of explicit specialization declarations for function templates, class templates, [...], can affect whether a program is well-formed according to the relative positioning of the explicit specialization declarations and their points of instantiation in the translation unit as specified above and below. When writing a specialization, be careful about its location; or to make it compile will be such a trial as to kindle its self-immolation.