没有生成的代码显式专门的模板,即使有显式实例化 [英] No generated code for explicitly specialized template even with explicit instantiation

查看:159
本文介绍了没有生成的代码显式专门的模板,即使有显式实例化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我从gcc 4.8.3和clang 3.2得到一致的行为,但不明白为什么会发生。尽管事实上我有一个类模板的显式实例化,代码不是生成的,当我使用一个完全专门的模板实例时,我得到一个未定义的符号。



我在文件'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方法

  #includetemp.hpp
#include< iostream>

template< typename T1>
void
C< T1> :: print()
{
std :: cout< Printing:<< d_c << std :: endl;
}

后面跟类型'float'的类的特殊化: p>

 模板<> 
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文件中,我必须明确实例化所有的专业化使用。所以我有:

 模板类C< int> ;; 
模板类C< float> ;;

我的测试的驱动程序在test.cpp中如下:

  #includetemp.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:未定义引用`C< float> :: print()'

C< int>。我可以看到它使用nm:

  nm -C temp.o 
...
0000000000000000 W C< int> :: print()
0000000000000000 W C< int> :: C(int)
0000000000000000 W C< int> :: C $ b

如前所述,这与gcc和clang一致,所以我假设有一些语言规则



请注意,如果我在temp.cpp文件中添加了print()方法的用法,则会生成代码,但这是愚蠢的在我真正的代码是不可能的。对于这个简单的测试用例,它看起来像:

  void foo()
{
C< float> ; s(1.3);
s.print();
}



在实际的代码中,我的模板有3个模板参数组合以扩展到约30个代码的排列。有一两个,我需要一个专业,做一些不同的东西,但其他28我可以单独留下。



任何指针,我走了错误或语言参考为什么显式实例化不应该生成代码是非常感谢。我花了半天时间阅读所有其他stackoverflow帖子显式实例化,并相信我正确使用它。

解决方案

From [temp.expl.spec]:


如果模板,成员模板或类模板的成员是显式专用的,专业化
在第一次使用该专业化之前必须被声明 ,这将导致隐式实例化
在每个翻译单元中发生发生这种使用;不需要诊断。如果程序
不提供明确的专门化的定义,并且专用化以某种方式使用将导致隐式实例化发生或成员是虚拟成员函数的
,则
$ b程序是错误的,无需诊断。


我们明确地专门化 C 在temp.cpp,但在test.cpp,它不是在使用之前声明。因此,您的代码是不成形的,无需诊断。您必须将 C< float> 的声明移动到temp.hpp中



始终小心显式专业化。

...]可以影响程序是否根据
良好地形成到如上下文所指定的翻译单元中的显式专用化声明及其实例化点
的相对定位。 编写专业化时,请注意其$​​ b $ b位置;



I'm getting consistent behavior from both gcc 4.8.3 and clang 3.2, but do not understand why it is happening. Despite the fact that I have an explicit instantiation for a class template, the code is not being generated and I get an undefined symbol when I am using a fully specialized instance of the template.

I have a simple class template definition in a file 'temp.hpp'

#pragma once

template <typename T1>
class C 
{
public:
  C (T1 c) : d_c(c) {};
  ~C () = default;

  void print ();
private:
  T1 d_c;
};

Note that the method 'print()' is declared, but not defined here. I want the definition in the .cpp file and it will be specialized for different types.

So in the temp.cpp file I have the default definition of the print() method

#include "temp.hpp"
#include <iostream>

template<typename T1>
void
C<T1>::print ()
{
  std::cout << "Printing: " << d_c << std::endl;
}

followed by a specialization of the class for the type '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;
};

and since the definitions are in the .cpp file I must explicitly instantiate all the specializations that I will be using. So I have:

template class C<int>;
template class C<float>;

The driver for my test looks like this in 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();
}

Upon compiling and linking this I get error:

test.cpp: undefined reference to `C<float>::print()'

The object code for the C< int > is properly generated. I can see it using nm:

nm -C temp.o
...
0000000000000000 W C<int>::print()
0000000000000000 W C<int>::C(int)
0000000000000000 W C<int>::C(int)
...

As I mentioned earlier, this is consistent with gcc and clang so I'm assuming there is some language rule I don't understand here.

Note that if I add a usage of the print() method in file temp.cpp, then the code is generated, but that is silly and in my real code would be impossible. For this simple test case it would look like:

void foo () 
{
  C<float> s(1.3);
  s.print();
}

In the real code which motivated this little test my template has 3 template arguments which combine to expand into about 30 permutations of the code. There are one or two of those for which I need a specialization which does something different, but the other 28 I can leave alone.

Any pointers on where I've gone wrong or a language reference for why the explicit instantiation of should not generate code are greatly appreciated. I've spent 1/2 a day reading all the other stackoverflow posts on explicit instantiation and believe I am using it correctly.

解决方案

From [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.

We're explicitly specializing C in temp.cpp, but in test.cpp, it is not declared before it is used. Thus, your code is ill-formed, no diagnostic required. You'll have to simply move the declaration of C<float> into temp.hpp

Always be careful with explicit specializations. The standard takes them very seriously:

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.

这篇关于没有生成的代码显式专门的模板,即使有显式实例化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆