2016-07-22 3 views
3

Zum Beispiel erfassen, habe ich folgenden C++ Code in der Header-DateiC++ Template-Programmierung für symmetrische Anordnung bei der Kompilierung

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

Und den folgenden Inhalt in seiner CPP-Datei definierte Array A Inhalt.

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

Gibt es eine Möglichkeit, eine Vorlage zu schreiben das Array A Inhalt ist symmetrisch zum Zeitpunkt der Kompilierung zu erkennen? (Wahrscheinlich C++ 11-Funktion unterstützt, aber ich bin nicht vertraut mit den Funktionen ...)

Zum Beispiel kann die DetectSymmetric<Data>::is_symtrue sein werden, wenn der Gehalt an A{1,2,2,1} und false ist, sagen, wenn es {1,2,3,4} gleich

Antwort

4

Mit C++ 14.11, können Sie eine constexpr Funktion:

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; 

Mit C++ 14, können Sie eine einfache for-Schleife anstelle der Rekursion schreiben kann, aber C 11 ++ hatte sehr strenge Einschränkungen für constexpr Funktionen.

+0

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

+0

auch, ich vermute, Sie meen's symmetric_helper' nicht 'symmetric_inside' im Helfer. – kfsone

+0

Sie haben Recht, ich habe es korrigiert. – Dutow

2

@Dutow war der erste mit einer funktionierenden Antwort, aber das sollte auch für die Typableitung sorgen und mit jeder Art von Arrays arbeiten können.

#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

Es gibt viele Modi zu tun, was Sie fragen.

Folgendes ist mein Weg.

Ich habe Ihre Data Struktur in variadic Template-Struktur geändert; nur um das Beispiel zu vereinfachen.

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

S.: Entschuldigung für mein schlechtes Englisch.

0

Hier ist eine C++ 14-Lösung (minimal, Arbeitsbeispiel):

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

Der Nachteil ist, dass es das gesamte Array iteriert.
Es kann verbessert werden, aber es ist eine Übung für den Leser.