另一个模板(同一类)的模板专业化

时间:2011-09-01 10:14:14

标签: c++ templates template-specialization specialization

我正在写一个数组类。此数组类可以再次包含数组作为成员。实现打印功能时,我需要专业化。

26:template <class T> class array : public vector<T>{
public:
    ...
       string* printToString();
    ...
};
...           
template <class T> string* array<T>::printToString(){
   ...  // generic function
}
template <> inline string* array<double>::printToString(){
   ...  // spezialization for double, works
}
561:template <class U> string* array<array<U>*>::printToString(){
   ...  // does not work
}

最后一个定义产生

src/core/array.h:561: error: invalid use of incomplete type ‘class array<array<T> >’
src/core/array.h:26: error: declaration of ‘class array<array<T> >’

如果重要的话,g ++版本是g ++(Ubuntu 4.4.3-4ubuntu5)4.4.3。 有什么想法是什么问题?

提前致谢, 托马斯

3 个答案:

答案 0 :(得分:4)

作为David解决方案的替代方案,您可以无条件地将调用转发给一组重载函数:

template <class T> class array;
namespace details {
  template <class T> std::string array_print(array<T> const&);
  std::string array_print(array<double> const&); // Regular function 
  template <class T> std::string array_print(array<array<T> > const&);
}

template <class T> class array : private vector<T> {
public:
    ...
       std::string printToString() { return details::array_print(*this); }
    ...
};

namespace details { /* implementions after class is defined */ }

答案 1 :(得分:3)

你不能部分专门化一个功能,你只能完全专门化它,这就是你可以为double而不是array<U> U提供专业化的原因。 {1}}是通用类型。

你可以通过使用类模板解决这个限制,并对其进行部分特殊处理,但这会有点麻烦。

namespace detail {
   template <typename T>
   struct array_printer {
      static std::string print( array<T> const & array ) {
         // basic implementation
      }
   };
   template <typename T>
   struct array_printer< array<T> > {
      static std::string print( array< array<T> > const & array ) {
         // specialization for array<T>
      }
   }
}

然后将成员函数实现为适当重载的简单调度:

template <typename T> 
class array : std::vector<T> {  // do not publicly derive from STL containers
public:
   std::string printToString() const {
      return detail::array_printer<T>::print( *this );
   }
}

当然,实际代码中的事情要复杂得多,你必须适当地订购代码,并提供模板的前向声明以及所有这些,但这应该足以让你开始。

答案 2 :(得分:1)

您的功能必须完全专业化。例如:

// Fully specialized. You cannot replace `double` with generic parameter.
template <>
string* array<array<double>*>::printToString(){
    return nullptr;
}

但是,您的课程可以部分专业化。例如:

template <class T> class array : public vector<T>{
public:
    string* printToString();
};

template <class T> string* array<T>::printToString(){
    return nullptr;
};

// Partial specialization.
template <class T> class array<array<T>*> : public vector<T>{
public:
    string* printToString();
};

template <class T> string* array<array<T>*>::printToString(){
    return nullptr;
};

- 编辑---

类通用类中的方法不会被类专门化“自动”采用,反之亦然。但是,您可以使用继承来“自动化”从泛型类重用方法。例如......

template <class T> class array : public vector<T>{
public:
    string* printToString();
    void f();
};

// (1a)
template <class T> string* array<T>::printToString(){
    return nullptr;
};

// (2)
template <class T> void array<T>::f(){
};

template <class T> class array<array<T>*> : public array<T> {
public:
    string* printToString();
};

// (1b)
template <class T> string* array<array<T>*>::printToString(){
    return nullptr;
};

void Test() {

    array<double> a1;
    a1.printToString(); // Calls (1a).
    a1.f(); // Calls (2).

    array<array<char>*> a2;
    a2.printToString(); // Calls (1b).
    a2.f(); // Calls (2).

}

......这可能是你需要的,也可能不是(可能需要一些“手动”重复)。