非模板类的模板成员函数的专业化

时间:2013-12-04 11:32:46

标签: c++ templates template-specialization member-functions

我想在cpp文件中定义模板函数的显式特化。那可能吗?更具体地说,我有以下代码,它们编译时没有错误:

//class.h
class myclass
{
public:
    /* Constructor */
    myclass();
    /* Trigger fcn */
    template<typename T> T Trigger(T rn);

private:
    /* Specializations of the templated Trigger(...) function */
    template<> int Trigger<int>(int rn)
    {
        int_do(rn);
    }
    template<> double Trigger<double>(double rn)
    {
        double_do(rn);
    }
}

但是,我在头文件中的定义对我来说看起来很奇怪,所以我想将这些定义与声明分开,如下所示:

//class.h
class myclass
{
public:
    /* Constructor */
    myclass();
    /* Trigger fcn */
    template<typename T> T Trigger(T rn);

private:
    /* Specializations of the templated Trigger(...) function */
    template<> int Trigger<int>(int rn);
    template<> double Trigger<double>(double rn);   
}

//class.cpp
/* Specializations of the templated Trigger(...) function */
template<> int myclass::Trigger<int>(int rn)
{
    int_do(rn);
}
template<> double myclass::Trigger<double>(double rn)
{
    double_do(rn);
}

有没有办法解决这个问题?

2 个答案:

答案 0 :(得分:9)

您唯一的错误是声明类中的特化。在标题中声明它们,但在类之外:

class myclass
{
public:
    myclass();
    template<typename T> T Trigger(T rn);
};

/* Specializations of the templated Trigger(...) function */
template<> int myclass::Trigger<int>(int rn);
template<> double myclass::Trigger<double>(double rn);   

然后您可以在源文件中定义它们,就像您一样。

请注意,您的第一个代码段不会编译(除非您的编译器具有非标准扩展名),因为无法在类中声明特化。

答案 1 :(得分:1)

除了早期关于专业化定位的答案:

您可以在.cpp文件中定义模板函数。这也意味着它们只能在此转换对象/文件中实例化。 在您的情况下,部分特化在.h中声明,其他编译单元将期望它们存在。

例如in file tmp.h:

#include <iostream>
class T {
public:
  template <typename T> void foo(const T& t)
  {
    std::cout << "generic foo" << std::endl;
  }
};
// forward declaration of specialization
template<> void T::foo(const double& t);

file tmp.cpp:

#include "tmp.h"

template <> void T::foo(const double& t)
{
  std::cout << "double foo" << std::endl;
}

文件main.cpp:

#include "tmp.h"
int main(int argc, const char** argv)
{
  T t;
  t.foo(1.0); 
  t.foo(1);
  return 0;
}

现在编译两个.cpp文件都可以正常工作:

g++ main.cpp tmp.cpp -o tmp
./tmp
double foo
generic foo

没有专业化的定义:

g++ main.cpp -o tmp
/tmp/ccpCJr3B.o: In function `main':
main.cpp:(.text+0x1f): undefined reference to `void T::foo<double>(double const&)'
collect2: error: ld returned 1 exit status