【问题标题】:c++ template class member function specializationc++模板类成员函数特化
【发布时间】:2013-09-24 10:59:41
【问题描述】:

我有一个问题,我想在下面的代码中专门化模板类的模板成员函数。这个问题的答案explicit specialization of template class member function 似乎表明它无法完成。这是正确的,如果是这样,我可以使用任何解决方法,以便通过内联 inc 函数在编译时扩展?

非常感谢!

#include <iostream>
#include <cstdio>

template <class IT, unsigned int N>
struct IdxIterator {
private:
  int startIdx[N], endIdx[N];  
  int curIdx[N];
  IT iter;

public:
  IdxIterator(IT it, int cur[], int start[], int end[]): iter(it) {
    for (int i = 0; i < N; i++) {
      curIdx[i] = cur[i];
      startIdx[i] = start[i];
      endIdx[i] = end[i];
    }
  }

  template <int dim>
  inline void inc() {
    curIdx[dim]++;
    if (curIdx[dim] > endIdx[dim]) {
      if (dim > 0) {
        curIdx[dim] = startIdx[dim];
        inc<dim-1>();
      }
    }
  }

  // how to declare this specialization?
  template <> template <>
  inline void inc<-1>() {
    std::cerr << "IdxIterator::inc(" << -1 << ") dim out of bounds!\n";
    throw 1;
  }

  inline IdxIterator<IT, N> operator++() {
    iter++;
    inc<N-1>();
    return *this;
  }

};

int main(int argc, char** argv) {

  int *buf = new int[100];
  int start[1], end[1];
  start[0] = 0; end[0] = 99;
  IdxIterator<int*, 1> it(buf, start, start, end);
  ++it;

  return 0;

}

G++ 吐槽:

test2.cpp:32:13: 错误:非命名空间范围内的显式特化 ‘struct IdxIterator’ test2.cpp:32:25:错误:显式 非命名空间范围“struct IdxIterator”的专业化 test2.cpp:33:23: 错误: 模板 ID ‘inc’ 在 主模板test2.cpp的声明:在成员函数'void IdxIterator::inc() [int dim = -0x000000000000003fe, IT = int*, unsigned int N = 1u]': test2.cpp:27:9: 错误: 模板 实例化深度超过最大值 1024(使用 -ftemplate-depth= 增加最大值)实例化'void IdxIterator::inc() [int dim = -0x000000000000003ff, IT = int*, unsigned int N = 1u]' test2.cpp:27:9: 从‘void IdxIterator::inc()递归实例化[with int dim = -0x00000000000000001, IT = int*, unsigned int N = 1u]' test2.cpp:27:9: 从'void IdxIterator::inc() [with int dim = 0, IT = int*, unsigned int N = 1u]'实例化 test2.cpp:41:5: 从‘IdxIterator 实例化 IdxIterator::operator++() [with IT = int*, unsigned int N = 1u]' test2.cpp:53:5: 从这里实例化

test2.cpp:在全局范围内:test2.cpp:22:15:警告:内联函数 'void IdxIterator::inc() [with int dim = -0x000000000000003ff, IT = int*, unsigned int N = 1u]' 使用但从未定义 [启用者 默认]

【问题讨论】:

  • 如果你的编译器支持 C++11,你可以使用static_assert。否则,您可以在 inc 内调用第二个模板(独立于 IdxIterator)的实例化来执行此检查。
  • 尽量减少你输入问题的代码!!!这里的大部分内容根本与问题无关。
  • 如果您唯一的问题是确保正值,这似乎很简单。 template&lt;unsigned var&gt; void foo() { /*impl*/ }

标签: c++ function templates specialization


【解决方案1】:

在 C++11 中可能有更好的方法,但你总是可以通过重载而不是特化:

template <int N>
struct num { };

class A
{
    template <int N>
    void f(num <N>) { };

    void f(num <-1>) { };

public:
    template <int N>
    void f() { f(num <N>()); };
};

【讨论】:

  • 这个答案需要对template&lt;&gt; num&lt;0&gt; {} 进行专门化,否则编译器在调用num&lt;n-1&gt;. 时将不知道何时终止
【解决方案2】:

你可以按照编译器错误信息的提示去做:

template <class IT, unsigned int N>
struct IdxIterator {
private:
  template <int dim>
  inline void inc() {
    curIdx[dim]++;
    if (curIdx[dim] > endIdx[dim]) {
      if (dim > 0) {
        curIdx[dim] = startIdx[dim];
        inc<dim-1>();
      }
    }
  }
};

template <> template <>
inline void IdxIterator::inc<-1>() {
  std::cerr << "IdxIterator::inc(" << -1 << ") dim out of bounds!\n";
  throw 1;
}

即将定义移动到命名空间范围。

【讨论】:

    【解决方案3】:

    在类之外创建一个辅助结构

    template<dim>
    struct inc {
    template<class cur, end>
          inline static void foo(cur curIdx, end endIdx) {
            curIdx[dim]++;
        if (curIdx[dim] > endIdx[dim]) {
            inc<dim-1>::foo(curIdx, endIdx);
          }
        }    
    };
    
    template<>
    struct inc<0> {
        template<class cur, end>
          inline static void foo(cur, end) {
           //terminate
        }    
    };
    
    class IdxIterator {
           template<int i>
           void inc() {
            static_assert(i > 0, "error out of bounds");
             int<i>::foo(/*params*/); 
        }
    
    };
    

    请注意,如果您使用的是 GCC,您可以__attribute__((always_inline))强制内联。

    【讨论】:

      猜你喜欢
      • 2012-04-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多