使用元编程计算 log2 但“编译终止”
Using meta-programming to calculate the log2 but `compilation terminated`
我是 TMP 的新手,我使用元编程编写了一个程序来计算 log2。我写了一个模板结构 power2
来计算幂,一个模板 class log2arr
里面有一个数组来保存结果,还有一个嵌入式模板结构 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;
}
}
但是编译器只告诉我compilation terminated.
这是什么意思?我该如何解决?
如有任何帮助,我们将不胜感激。
您的代码存在一些问题,我将展示其中的一些问题,排名不分先后。
(1) struct/class 内不允许完全特化;所以你不能完全专业化 log2
inside log2arr
.
您可以将 log2
迁移到 log2arr
之外,或者,如果您真的想在 log2arr
内部维护它,您可以将完全专业化转换为等效的部分专业化(在 log2arr
中是合法的) =111=]);举例如下
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()
return 一个 int *
,你丢失了关于 log2Arr
class 中数组的信息;所以不适用于基于范围的for循环(for(auto i : a.getArr())
)。
不幸的是,您不能 return C 样式数组(您不能 return arr
本身)。
但是你使用的是 C++11 或更新版本(你只标记了 C++ 但你使用的是基于范围的 for 循环,所以你至少使用了 C++11)所以我强烈建议你定义arr
作为 std::array<int, N>
,而不是 C 风格的数组(不是 int arr[N]
)。我强烈建议你 return 引用 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()
.[=65 时都会初始化 arr
=]
此外:您不能在另一个方法中使用 arr
(如果您想添加另一个方法),而无需在另一个方法中对其进行初始化。
建议:初始化arr
,一次性,在显式构造函数中;举个例子
log2arr ()
{ log2<N>().set(arr); }
所以你的 getArr()
方法就变成了
arrT & getArr ()
{ return arr; }
arrT const & getArr () const
{ return arr; }
(5) log2<I>
初始化 arr[I]
和 log<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) 不需要初始化a
如下
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, std::integral_constant<bool, 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;
}
我是 TMP 的新手,我使用元编程编写了一个程序来计算 log2。我写了一个模板结构 power2
来计算幂,一个模板 class log2arr
里面有一个数组来保存结果,还有一个嵌入式模板结构 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;
}
}
但是编译器只告诉我compilation terminated.
这是什么意思?我该如何解决?
如有任何帮助,我们将不胜感激。
您的代码存在一些问题,我将展示其中的一些问题,排名不分先后。
(1) struct/class 内不允许完全特化;所以你不能完全专业化 log2
inside log2arr
.
您可以将 log2
迁移到 log2arr
之外,或者,如果您真的想在 log2arr
内部维护它,您可以将完全专业化转换为等效的部分专业化(在 log2arr
中是合法的) =111=]);举例如下
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()
return 一个 int *
,你丢失了关于 log2Arr
class 中数组的信息;所以不适用于基于范围的for循环(for(auto i : a.getArr())
)。
不幸的是,您不能 return C 样式数组(您不能 return arr
本身)。
但是你使用的是 C++11 或更新版本(你只标记了 C++ 但你使用的是基于范围的 for 循环,所以你至少使用了 C++11)所以我强烈建议你定义arr
作为 std::array<int, N>
,而不是 C 风格的数组(不是 int arr[N]
)。我强烈建议你 return 引用 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()
.[=65 时都会初始化 arr
=]
此外:您不能在另一个方法中使用 arr
(如果您想添加另一个方法),而无需在另一个方法中对其进行初始化。
建议:初始化arr
,一次性,在显式构造函数中;举个例子
log2arr ()
{ log2<N>().set(arr); }
所以你的 getArr()
方法就变成了
arrT & getArr ()
{ return arr; }
arrT const & getArr () const
{ return arr; }
(5) log2<I>
初始化 arr[I]
和 log<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) 不需要初始化a
如下
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, std::integral_constant<bool, 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;
}