4

我的一个类声明了一个模板函数:

template<class A, class B>
A do_something(const std::vector<B> &data)

我想部分专注于typename A. B是一个实现了一个非常小的接口的类型家族,我们使用了很多,所以我希望我的专长是通用的B。我怀疑这是双重烦恼,因为typename A它仅用作返回类型。

从互联网上,我了解到我不能部分专门化一个函数,所以我创建了一个类,如下所示:

template<class A, class B> 
class do_something_implementation {
  public:
    do_something_implementation(const std::vector<B> &data_) {
      data = data_;
    }

  int do_something_implementation<int, B>::operator()() {
    /* Complicated algorithm goes here... */
  }

  double do_something_implementation<double, B>::operator()() {
    /* Different complicated algorithm goes here... */
  }

  private:
      std::vector<B> data;
}

当我尝试编译它(使用 Visual Studio 2008)时,编译器崩溃(!)并且我收到以下错误:

fatal error C1001: An internal error has occurred in the compiler.

我认为这是我的问题,而不是编译器的问题。有没有更好的方法来表达我想要的部分专业化?

4

4 回答 4

7

通常,它是这样的:

template <typename A, typename B>
struct DoSomethingHelper
{
    static A doIt(const std::vector<B> &data);
};

template <typename B>
struct DoSomethingHelper<double, B>
{
    static double doIt(const std::vector<B> &data) { ... }
};

template <typename B>
struct DoSomethingHelper<int, B>
{
    static int doIt(const std::vector<B> &data) { ... }
};

template<class A, class B>
A do_something(const std::vector<B> &data)
{ return DoSomethingHelper<A, B>::doIt(data); }
于 2010-12-14T14:31:59.797 回答
4

既然您已经看到了经典的 forward to static 方法,实际上还有另一种方法,即要专门针对的类型是“完整的”。

你可能无法部分特化一个函数,但你可以完美地重载它。

template <typename A, typename B>
A do(std::vector<B> const& data) { return this->doImpl(data, (A*)0); }

template <typename A, typename B>
A doImpl(std::vector<B> const& B, A*) { // generic implementation }

template <typename B>
int doImpl(std::vector<B> const& B, int*) { // int implementation }

template <typename B>
double doImpl(std::vector<B> const& B, double*) { // double implementation }

诀窍是传递一个“未使用”的参数来doImpl实际选择正确的实现(感谢重载决议)。

这里我只是简单地选择了 pass (A*)0,因为这不涉及A' 的构造函数(以防万一)。

这种调度惯用语是 STL 中用于实现某些迭代器类别效率更高的算法(例如,std::distance对于随机迭代器来说是 O(1))。

我发现使用具有静态方法和部分专业化的辅助类更轻量级......但也许这只是我:)

于 2010-12-14T15:42:31.207 回答
1

人们通常只是转发到静态实现。

template<class A, class B> class X;
template<class A, class B> friend class X;
template<class A, class B> class X {
public:
    static A do_something(class_type* not_this, const std::vector<B>& data) {
        //...
    }
};
// partially specialize
template<class A, class B>
A do_something(const std::vector<B> &data) {
    return X<A, B>::do_something(this, data);
};
于 2010-12-14T14:31:53.307 回答
1

不是您的问题的解决方案(已经有几个),但是您的代码中有一些错误的地方:

您在模板类声明中缺少structorclass关键字:

template <typename A, typename B> struct do_something_implementation {
//                                ^^^^^^

在类定义中,成员函数不得使用限定名称,无论该类是否为模板:

class A {
   void A::foo() {} // Error, should be: void foo() {}
};

成员模板特化不能出现在类定义中,而是出现在命名空间级别:

class B {
   template <typename T> void foo( T );
};
template <> void B::foo<int>( int ) {}
template <> void B::foo<double>( double ) {}

另外,在您的情况下,成员函数不是模板,而是非模板成员函数(模板是包含类,而不是函数本身)。您的代码实际上试图做的是在通用模板中定义其他类的成员函数,有点试图做。

总体而言,有足够多的错误使编译器几乎不可能解析代码来识别您尝试执行的操作并提供良好的错误消息,但它仍然应该提供指向您复制的第一行的任何错误消息,而不是窒息而死。

于 2010-12-14T17:09:30.347 回答