CPP模板成员函数特化

3
我正在尝试专门化成员函数moment()(而不是整个类),像这样:

template<class Derived, class T>
class AbstractWavelet {
public:
  [...]

  template<bool useCache>
  const typename T::scalar moment(const int i, const int j) const {
    return abstractWaveletSpecialization<Derived, T, useCache>::moment(static_cast<const Derived*>(this), i, j);
  }
  template<bool useCache>
  friend const typename T::scalar abstractWaveletSpecialization<Derived, T, useCache>::moment(const Derived* const that, const int i, const int j);

protected:
  // returns the jth moment of the ith scaling function
  template<bool useCache>
  inline const typename T::scalar momentImpl(const int j, const int i) const {
    [...]
  } // momentImpl
};

实际的专业化发生在一个额外的abstractWaveletSpecialization结构中:
template<class Derived, class T, bool useCache>
struct abstractWaveletSpecialization {
  inline static const typename T::scalar moment(const Derived* const that, const int i, const int j) {
    return that->momentImpl<useCache>(i,j);
  }
};


template<class Derived, class T> 
struct abstractWaveletSpecialization<Derived, T, true> {

  typedef const std::pair<const int, const int> momentCacheKey;
  typedef std::map<momentCacheKey,
               const typename T::scalar> momentCacheType;
  static momentCacheType momentCache;


  inline static const typename T::scalar moment(const Derived* const that, const int i, const int j) {
    momentCacheKey cacheKey(i,j);
    typename momentCacheType::iterator idx = momentCache.find(cacheKey);

    if (idx == momentCache.end())
      return that->momentImpl<true>(i, j);  // COMPILE ERROR HERE
    else
      return momentCache[cacheKey];
  }
};

问题在于我无法在专门的abstractWaveletSpecialization结构中调用momentImpl()函数:
error: invalid operands of types ‘<unresolved overloaded function type>’ and ‘bool’ to binary ‘operator<’

但是编译器不会对非特化的abstractWaveletSpecialization结构中momentImpl函数的调用进行投诉。

我的做法在C++中被禁止了吗?还是有其他方法可以让这个工作起来?


1个回答

2

请尝试使用that->template momentImpl<true>(i, j);。 这是一种告诉编译器“嘿,->后面的东西是一个模板调用”的方法。


是的,这很不寻常。但是在使用高级模板化C++时就需要这样做 :-) - Scharron
1
@手册:问题在于A->B<C,其中AB是模板。当编译器首次遇到这些模板时(尚未替换任何模板参数),编译器不知道B是什么,因为这取决于A的类型,而A尚未实例化。(想一想特化的A可能会将B定义为与基本模板中不同的内容。)如果B最终是一个成员模板,则A->B<C应该是A->B<C>的开始。如果它是一个对象,那么应该检查A->B<C是否小于C。这就是为什么需要提示编译器的原因。 - sbi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接