c – 使用元编程来计算log2但是`编译终止’
我是TMP的新手,我使用元编程编写了一个程序来计算log2.我编写了一个模板struct power2来计算功率,一个模板类log2arr,其中包含一个数组以保存结果,还有一个嵌入式模板struct log2来计算log2值.
#include <iostream> template <int i> struct power2 { enum { value = (1 << i) }; }; template <int n> class log2arr { int arr[n]; template <int i> struct log2 { log2<i - 1> _arr; enum { value = log2<i - 1>::value + (power2<log2<i - 1>::value>::value == i) }; void print() { _arr.print(); std::cout << value << std::endl; } void set() { _arr.set(); arr[i] = value; } }; template <> struct log2<1> { enum { value = 1 }; void print() {} void set() {} }; public: int *getArr() { log2<n>().set(); return arr; } }; int main() { log2arr<4> a = log2arr<4>(); for(auto i : a.getArr()){ cout << i; } } 但编译器只告诉我编译终止. 这是什么意思?我该如何解决? 任何帮助将不胜感激. 解决方法
你的代码有一些问题,我会以一些特定的顺序展示它们中的一些.
(1)在struct / class中不允许完全特化;所以你不能在log2arr里面完全专门化log2. 你可以在log2arr之外迁移log2,或者,如果你真的希望将它保存在log2arr中,你可以在一个等价的部分特化中转换完全特化(在struct / class中合法);例如,如下 template <int I,typename = std::true_type> struct log2 { // body of the struct }; template <int I> struct log2<I,std::integral_constant<bool,I == 1>> { // body of the struct specialization }; (2)如果从getArr()返回一个int *,则会丢失有关log2Arr类中数组的信息;所以不适用于基于循环的范围(for(auto i:a.getArr())). 不幸的是你不能返回一个C风格的数组(你不能返回arr本身). 但是你使用的是C 11或更新版本(你只标记C但是你使用的是基于范围的循环,所以你至少使用C 11)所以我强烈建议你将arr定义为std :: array< int,N>,而不是C风格的数组(不是int arr [N]).我强烈建议你返回一个arr本身的引用(你可以使用std :: array) private: using arrT = std::array<int,N>; arrT arr {}; // ... public: arrT & getArr () { /* ... */ return arr; } 我还建议为const对象添加一个getArr() arrT const & getArr () const { /* ... */ return arr; } (3)你不能在嵌入式结构log2的方法里面管理arr数组(不是log2Arr的静态成员) void set() { _arr.set(); arr[i] = value; // <--- arr is inaccessible } 一个可能的解决方案是传递arr作为参考,所以 void set (arrT & a) // arrT = std::array<int,N> { _arr.set(a); a[i] = value; } 和(在log2< 1>中) void set (arrT &) {} 显然你必须调用set()传递arr作为参数,所以 log2<N>().set(arr) (4)在getArr()内部初始化arr是一个坏主意(恕我直言),因为每次调用getArr()时都会初始化arr. 而且:你不能在另一个方法中使用arr(如果你想添加另一个方法)而不在另一个方法中初始化它. 建议:在显式的构造函数中初始化arr,一次性.通过例子 log2arr () { log2<N>().set(arr); } 所以你的getArr()方法就变成了 arrT & getArr () { return arr; } arrT const & getArr () const { return arr; } (5)log2< I>初始化arr [I]并记录< 1>没有初始化,你的int arr [N]包含未被初始化的arr [0]和arr [1]值. 您可以将这些值初始化为零写入 int arr[N] {}; 或(使用std :: array< int,N>) using arrT = std::array<int,N>; arrT arr {}; // ^^ <--- initialize all to zero 但你必须决定如何在arr [0]和arr [1]中初始化 (6)没有需要初始化如下 log2arr<4> a = log2arr<4>(); 你可以简单地写 log2arr<4> a; ————————————— 以下是修改后的代码 #include <array> #include <iostream> template <int I> struct power2 { enum { value = (1 << I) }; }; template <int N> class log2arr { private: using arrT = std::array<int,N>; arrT arr {}; template <int I,typename = std::true_type> struct log2 { log2<I-1> _arr; enum { value = log2<I-1>::value + (power2<log2<I-1>::value>::value == I) }; void print () { _arr.print(); std::cout << value << std::endl; } void set (arrT & a) { _arr.set(a); a[I] = value; } }; template <int I> struct log2<I,I == 1>> { enum { value = 1 }; void print() {} void set(arrT &) {} }; public: log2arr () { log2<N>().set(arr); } arrT & getArr () { return arr; } arrT const & getArr () const { return arr; } }; int main () { log2arr<4> a; for ( auto i : a.getArr() ) std::cout << i; std::cout << std::endl; } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |