用于在编译时检测对称数组的c ++模板编程

时间:2016-07-22 16:12:08

标签: c++ arrays templates c++11

例如,我在头文件中有以下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功能支持,但我不熟悉它的功能......)

例如,如果DetectSymmetric<Data>::is_sym的内容为trueA,则{1,2,2,1}将为false,例如,如果它等于{1,2,3,4}

4 个答案:

答案 0 :(得分: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函数有非常严格的限制。

答案 1 :(得分: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");
}

答案 2 :(得分:0)

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

以下是我的方式。

我在variadic模板结构中修改了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;
 }

p.s:抱歉我的英语不好。

答案 3 :(得分: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), "!");
}

缺点是它遍历整个数组 它可以改进,但它留给读者练习。