用于在编译时检测对称数组的c++模板编程
c++ template programming for detecting symmetric array at compile time
例如,我在头文件中有以下c++代码
struct Data {
static const int N = 4;
static const int A[N];
};
并在其cpp文件中定义以下内容的数组A
内容。
const int Data::A[Data::N] = {1,2,2,1};
有没有任何方法可以编写一个模板来检测数组A
的内容在编译时是对称的?(可能c++11功能支持这一点,但我不熟悉它的功能…)
例如,如果A
的内容是{1,2,2,1}
和false
,则DetectSymmetric<Data>::is_sym
将是true
,例如,如果它等于{1,2,3,4}
使用C++11/14,您可以使用constexpr
函数:
const int A[4] = { 1,2,2,1 };
template<int N>
constexpr bool symmetric_helper( const int (&a)[N], int idx) {
return idx > 0 ? symmetric_helper<N>(a, idx - 1) && (a[idx - 1] == a[N - idx]) : true;
}
template<int N>
constexpr bool symmetric(const int (&a)[N]) {
return symmetric_helper<N>(a, N / 2);
}
std::cout << symmetric(A) << std::endl;
使用C++14,您可以编写一个简单的for循环,而不是递归,但C++11对constexpr
函数有非常严格的限制。
@Dutow是第一个给出有效答案的人,但这也应该考虑到类型推导,并且能够处理任何类型的数组。
#include <cstddef>
template<typename T, size_t N, size_t O, size_t I>
struct detect_symmetric_array
{
static constexpr bool is_symmetric(T (&array)[N])
{
return array[O] == array[N - O - 1] && detect_symmetric_array<T, N, O + 1, I - 1>::is_symmetric(array);
}
};
template<typename T, size_t N, size_t O>
struct detect_symmetric_array<T, N, O, 1>
{
static constexpr bool is_symmetric(T(&array)[N])
{
return array[O] == array[N - O - 1];
}
};
template<typename T, size_t N>
constexpr bool is_symmetric_array(T (&array)[N])
{
return detect_symmetric_array<T, N, 0, N / 2>::is_symmetric(array);
}
int main(int argc, char** argv)
{
constexpr int first[4] = { 1, 2, 2, 1 }, second[4] = { 1, 2, 3, 4 }, third[5] = {1, 2, 3, 2, 1}, foruth[5] = {1,3,2,4,5};
static_assert(is_symmetric_array(first), "array first should be symmetric");
static_assert(is_symmetric_array(second) == false, "array second should not be symmetric");
static_assert(is_symmetric_array(third), "array third should be symmetric");
static_assert(is_symmetric_array(foruth) == false, "array fourth should not be symmetric");
}
有很多模式可以满足您的要求。
下面是我的路。
我已经在可变模板结构中修改了您的Data
结构;只是为了简化示例。
template <int ... Is>
struct Data
{
static constexpr int N { sizeof...(Is) };
static constexpr int A[N] { Is... };
};
template <typename T, int P1 = 0, int P2 = T::N-1, bool B = (P1 < P2)>
struct is_sym;
template <typename T, int P1, int P2>
struct is_sym<T, P1, P2, false>
{ constexpr static bool value = true; };
template <typename T, int P1, int P2>
struct is_sym<T, P1, P2, true>
{
constexpr static bool value
= (T::A[P1] == T::A[P2]) && is_sym<T, P1+1, P2-1>::value ;
};
int main ()
{
static_assert(is_sym<Data<1, 2, 3, 4>>::value == false, "!");
static_assert(is_sym<Data<1, 2, 2, 1>>::value == true, "!");
static_assert(is_sym<Data<1, 2, 3, 2, 1>>::value == true, "!");
return 0;
}
抱歉我英语不好。
这里有一个C++14解决方案(最小的工作示例):
#include<functional>
#include<cstddef>
struct Data {
static const int N = 4;
static constexpr int A[N] = {1,2,2,1};
static constexpr int B[N] = {1,1,3,1};
};
template<typename T, std::size_t... I>
constexpr bool f(const T *data, std::index_sequence<I...>) {
bool eq = true;
int arr[] = { (eq &= (data[I] == data[sizeof...(I)-I-1]), 0)... };
return eq;
}
template<typename T, std::size_t N>
constexpr bool f(const T(&data)[N]) {
return f(data, std::make_index_sequence<N>());
}
int main() {
static_assert(f(Data::A), "!");
static_assert(not f(Data::B), "!");
}
缺点是它在整个数组上进行迭代
它可以改进,但留给读者练习。
相关文章:
- 有一个打印语句的函数是一种糟糕的编程实践吗
- 我是C++编程的新手,这些代码之间有什么区别,我应该使用哪一个
- 模板元编程:如何将参数包组合成新的参数包
- Qt Q串行端口未编程设备未关闭
- 模板元编程 - 尝试实现维度分析
- 我是编程新手
- C++编程从外部文本文件定义数组大小
- 了解算法的性能差异(如果以不同的编程语言实现)
- 使用 Gtkmm 以编程方式选择 Gtk::TextView 中的文本
- 如何将可变参数模板转换为多个单个模板?(C++竞争编程调试模板)
- 使用命名空间正确编程
- C++编程:运算符重载中的引用如何工作?
- Arduino 模块化编程与全局和设置
- C++ 运算符修改/元编程策略,用于不那么冗长的语法
- 在没有管理员权限的情况下,在 c++ 中以编程方式将程序添加到启动
- 如何以编程方式将音频从任何录制设备路由到任何播放设备
- 试图修复一个错误,该错误不会让我开始编程其余部分
- C++模板编程设计问题 - 根据输入文件返回不同的类型
- Frank Luna 在他的书"使用 DirectX12 进行 3D 游戏编程"的介绍中盒子示例的问题
- 如何使用可变参数模板类使用模板元编程获得最大值