2016-07-22 99 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), "!"); 
} 

的缺點是,它遍歷整個陣列。
它可以改進,但它是作爲一個練習留給讀者。