c++ (XORString): "recursive type or function dependency context too complex"

c++ (XORString): "recursive type or function dependency context too complex"

本文关键字:function dependency context complex too or recursive XORString c++ type      更新时间:2023-10-16

我正在尝试在编译时间使用以下Xorstring模板/宏来加密字符串文字:

#pragma once
#include <string>
namespace utils {
    template <int X> struct EnsureCompileTime {
        enum : int {
            Value = X
        };
    };
    //Use Compile-Time as seed
#define compile_seed (  (__TIME__[7] - '0') * 1  + (__TIME__[6] - '0') * 10     +   
                            (__TIME__[4] - '0') * 60   + (__TIME__[3] - '0') * 600  +   
                            (__TIME__[1] - '0') * 3600 + (__TIME__[0] - '0') * 36000    )
    constexpr int LinearCongruentGenerator(int Rounds) {
        return 1013904223 + 1664525 * ((Rounds > 0) ? LinearCongruentGenerator(Rounds - 1) : compile_seed & 0xFFFFFFFF);
    }
#define Random() EnsureCompileTime<LinearCongruentGenerator(10)>::Value //10 Rounds
#define RandomNumber(Min, Max) (Min + (Random() % (Max - Min + 1)))
    template <int... Pack> struct IndexList {};
    template <typename IndexList, int Right> struct Append;
    template <int... Left, int Right> struct Append<IndexList<Left...>, Right> {
        typedef IndexList<Left..., Right> Result;
    };
    template <int N> struct ConstructIndexList {
        typedef typename Append<typename ConstructIndexList<N - 1>::Result, N - 1>::Result Result;
    };
    template <> struct ConstructIndexList<0> {
        typedef IndexList<> Result;
    };
    template <typename Char, typename IndexList> class XorStringT;
    template <typename Char, int... Index> class XorStringT<Char, IndexList<Index...> > {
    private:
        Char Value[sizeof...(Index)+1];
        static const Char XORKEY = static_cast<Char>(RandomNumber(0, 0xFFFF));
        template <typename Char>
        constexpr Char EncryptCharacterT(const Char Character, int Index) {
            return Character ^ (XORKEY + Index);
        }
    public:
        __forceinline constexpr XorStringT(const Char* const String)
            : Value{ EncryptCharacterT(String[Index], Index)... } {}
        const Char *decrypt() {
            for (int t = 0; t < sizeof...(Index); t++) {
                Value[t] = Value[t] ^ (XORKEY + t);
            }
            Value[sizeof...(Index)] = static_cast<Char>(0);
            return Value;
        }
        const Char *get() {
            return Value;
        }
    };
#define XORSTR( String ) ( utils::XorStringT<char, utils::ConstructIndexList<sizeof( String ) - 1>::Result>( String ).decrypt() )
}

代码不是我的,我对C 模板或元编程知之甚少。该代码按照针对的小字符串(&lt; 250个字符)的作用,但是,我还需要使其在长字符串(数千个字符)上工作。

当我在带有数千个字符的字符串文字上使用XORSTR宏时,我在编译过程中获得了"递归类型或函数依赖性上下文过于复杂"错误。

我已经尝试确切地弄清楚代码的作用,并且似乎这些行递归地从输入字符串递归构造某种编译时间阵列(?),而ConstructIndexList行是生成错误的原因:

template <typename IndexList, int Right> struct Append;
    template <int... Left, int Right> struct Append<IndexList<Left...>, Right> {
        typedef IndexList<Left..., Right> Result;
    };
    template <int N> struct ConstructIndexList {
        typedef typename Append<typename ConstructIndexList<N - 1>::Result, N - 1>::Result Result;
    };

由于我对模板的了解很少,因此我不确定如何确切解决此问题。

我的一个想法是通过原始文字的宏观亚字符串,然后将它们连接起来(以程序的方式,而不是手动),但是...我不知道如何进行编译时串联/串联操作文字,也许这是不可能的。

另一个想法是简单地手动将我的文字拆分,将拆分字符串分别传递给XORSTR,然后手动将结果串联到结果中,但这会在我的代码中造成很多混乱。...考虑到我需要运行XORSTR在数以万计的字符上,当传递> 〜250个字符时,错误会弹出。

任何其他想法都将不胜感激...或者如果某人拥有另一个可以使用任何任意长度的字符串文字的编译时字符串混淆实现……那将很棒!

如果我没有错,则您的 ConstructIndexList make(rougly)std::make_integer_sequence的工作(可从C 14获得)。

所以我想你可以写

template <typename>
struct cilH;
template <int ... Is>
struct cilH<std::integer_sequence<int, Is...>>
 { using type = IndexList<Is...>; };
template <int N>
struct ConstructIndexList
 { using Result = typename cilH<decltype(std::make_integer_sequence<int, N>{})>::type; };

避免递归瓶颈。

(但请记住到#include <utility>)。

但是,我想,如果您使用类型std::size_t而不是int,则可以完全避免使用ConstructIndexList

我想您的代码可以如下简化

#include <array>
#include <string>
#include <utility>
#include <iostream>
namespace utils
 {
   constexpr std::size_t compSeed {
          (__TIME__[7] - '0') * 1U
        + (__TIME__[6] - '0') * 10U
        + (__TIME__[4] - '0') * 60U
        + (__TIME__[3] - '0') * 600U
        + (__TIME__[1] - '0') * 3600U
        + (__TIME__[0] - '0') * 36000U };
   constexpr std::size_t linCongrGen (std::size_t rou)
    { return 1013904223U + 1664525U * ((rou > 0U)
        ? linCongrGen(rou - 1U)
        : compSeed & 0xFFFFFFFFU); }
   constexpr std::size_t randNumber (std::size_t mn, std::size_t mx)
    { return mn + (linCongrGen(10U) % (mx - mn + 1U)); }
   template <typename, typename>
   class XorStringT;
   template <typename Char, std::size_t ... Is>
   class XorStringT<Char, std::index_sequence<Is...>>
    {
      private:
         Char Value[sizeof...(Is)+1U];
         static constexpr Char XORKEY = Char(randNumber(0, 0xFFFF));
      public:
         constexpr XorStringT (Char const * const String)
            : Value{ Char(String[Is] ^ (XORKEY + Is))... }
          { }
         constexpr std::array<Char, sizeof...(Is)+1U> decrypt () const
          { return { { Char(Value[Is] ^ (XORKEY + Is)) ..., Char(0) } }; }
         Char const * get () const
          { return Value; }
    };
 }
template <typename T, std::size_t N>
constexpr auto xorStr (T (&s)[N])
 { return utils::XorStringT<T,
      decltype(std::make_index_sequence<N - 1U>{})>( s ); }
int main()
 {
   constexpr auto xst = xorStr("secrettext");
   std::cout << xst.get() << std::endl;
   std::cout << xst.decrypt().data() << std::endl;
 }

编译器具有限制,您正在尝试将模板嵌套到字符串长度的深度中。几年前,您的编译器会为此烧毁您的计算机,今天您会收到一条不错的错误消息,将来不太可能改善。(即使编译器实际上找到了到字符串末端的方式,您也会对编译的速度感到不满意。)

您应该考虑脱机编码文字 - 即,使用一个单独的工具(通过您的Makefile或您拥有的任何构建系统)在选定的源标头上生成生成的标头(或CPP,其他) - 后者您#include。也许您可以重新利用现有的可编程模板生成器,也许您可以使用代码中的"标记"的现有工具来指示要编码的字符串 - awk在这里可以很好地工作 - 您甚至可以将字符串放在单独的"消息"文件中并从中生成标头。

P.S。这些限制中的一些已记录在特定编译器的文档中。您可以在此处查找模板嵌套的限制,或在模板变化参数的数量上查找限制。据我所知,标准仅提示这些最大限制的最低限度,而这些非常低。