2016-07-22 101 views
3

检测对称阵列例如,我有在头文件C++模板编程为在编译时

struct Data { 
    static const int N = 4; 
    static const int A[N]; 
}; 

以下C++代码,并在其CPP文件中的以下内容来定义的阵列A内容。

const int Data::A[Data::N] = {1,2,2,1}; 

有什么办法来编写模板来检测数组A内容在编译时是对称的吗? (可能是C++ 11的功能支持,但我不熟悉它的功能...)

例如,DetectSymmetric<Data>::is_symtrue如果A含量为{1,2,2,1}false,说如果它等于{1,2,3,4}

回答

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,你可以写一个简单的循环,而不是递归,但C++ 11有对于constexpr功能非常严格的限制。

+0

'sizeof(a)'=='sizeof(const int *)''。 – kfsone

+0

另外,我猜你在助手中的意思是'symmetric_helper'不是'symmetric_inside'。 – kfsone

+0

你说得对,我纠正了它。 – Dutow

2

@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"); 
} 
0

有很多模式可以做你所要求的。

以下是我的方法。

我修改了你的Data结构variadic模板结构;只是为了简化这个例子。

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; 
} 

对不起,我的英语不好。

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), "!"); 
} 

的缺点是,它遍历整个阵列。
它可以改进,但它是作为一个练习留给读者。