Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/148.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;元编程-编译时搜索树_C++_Binary Tree_Template Meta Programming - Fatal编程技术网

C++ C++;元编程-编译时搜索树

C++ C++;元编程-编译时搜索树,c++,binary-tree,template-meta-programming,C++,Binary Tree,Template Meta Programming,更新:抱歉混淆了术语-我不需要二叉树,但需要段树或区间树 想象一下,每次执行我的程序时,我都必须静态初始化一个搜索树 Tree t; t.add(10, 'Apple'); t.add(20, 'Pear'); t.add(50, 'Orange'); ... t.add(300, 'Cucumber'); .. // then I use it. int key = 15; String s = t.lookup(key) // Returns 'Apple' ( as the key is

更新:抱歉混淆了术语-我不需要二叉树,但需要段树或区间树

想象一下,每次执行我的程序时,我都必须静态初始化一个搜索树

Tree t;
t.add(10, 'Apple');
t.add(20, 'Pear');
t.add(50, 'Orange');
...
t.add(300, 'Cucumber');

..
// then I use it.
int key = 15;
String s = t.lookup(key) // Returns 'Apple' ( as the key is between 10 and 20)
树中的键和值是“静态”的、硬编码的,但必须不时进行维护。是否有元编程技巧,如何在编译时将键值组织到二进制搜索树(或跳过列表)中


例如,整个搜索树直接在code
.text
中实现,而
中没有任何内容?我还可以“预测”键的数量并对它们进行排序。

我会使用
开关来进行查找

编译器可以自由使用跳转表、二进制搜索或任何其他技术来优化查找。对于大多数开关表,编译器通常会发出尽可能快的消息

switch (key)
{
    case 10: return "Apple";
    case 20: return "Pear";
    ...
}

我怀疑你在小题大做, 这是因为:-

    <>你相信在C++中静态初始化某些东西 必须在编译时间完成

  • 要么你不熟悉这本书 上界和下界的概念,否则你不知道 [部分]有序序列
    S
    v
    的{上界|下界}可以是 通过对
    S
    的二进制搜索确定,您可以使用标准库 至少这样做是有效率的

我认为您需要一个静态初始化的数据结构映射 字符串文本的整数键,以便在运行时 可以使用整数
n
高效地查询它 检索字符串literal
s
(如果有),其键是最大的 不大于
n
——加上附加的但书,
n
不大于所有键

如果这是正确的,那么您需要的静态初始化数据结构 只是一个静态初始化的整数到字符串文本的映射
M
。 模板元编程不在框架中

由于(假定的)但书,查询将在
n
较大的时间内失败 与所有键相比,您需要使用键1在
M
中包含一个sentinel值 比你想找到的最大的要大

然后,对于运行时整数
n
,您可以查询
M
以获得
n
的上限。
M
n
的上限是大于
n
的最小键(如果有)。 如果返回的迭代器
it
M.end()
,则您没有
n
的字符串。 否则,如果
it==M.begin()
,则每个键都大于
n
, 同样,您没有
n
的字符串。否则,必须存在一个
位于
--它
,并且该
键必须是不是最大的键
大于
n
。因此,
n
的字符串就是

#include <map>

static const std::map<int,char const *> tab = 
{
    { 2,"apple" },
    { 5,"pear" },
    { 9,"orange" },
    { 14,"banana" },
    { 20,"plum" },
    { 20 + 1,nullptr }
};

const char * lookup(int n)
{
    auto it = tab.upper_bound(n);
    return it == tab.begin() || it == tab.end() ? nullptr : (--it)->second;
}
现在这个程序中的
tab
是一个静态数据结构,但它不是 在编译时初始化。它在全局静态文件中初始化 在调用
main
之前初始化程序。除非你 我想,你的程序启动需要节省纳秒的时间 想不出为什么需要在编译时初始化映射

但是,如果确实需要在编译时对其进行初始化, 只是比这更烦躁。你需要把地图弄清楚 A. 对象,这意味着编译器可以在编译时构造它;以及 它必须是一个; 这意味着您不能使用
std::map
,因为它不是文本类型

因此,您必须改用:

constexpr std::pair<int,char const *> tab[] 
{
    { 2,"apple" },
    { 5,"pear" },
    { 9,"orange" },
    { 14,"banana" },
    { 20,"plum" },
    { 20 + 1,nullptr }
};   
constepr std::pair tab[]
{
{2,“苹果”},
{5,“梨”},
{9,“橙色”},
{14,“香蕉”},
{20,“李子”},
{20+1,nullptr}
};   
或类似的方法,并基本上按照所示的方式执行
查找(n)
, 但是在
选项卡上调用
std::upper_bound
。在那里你会发现 稍微有点烦躁,如果你愿意的话,我会把它留给你做练习
想要它。

我终于创造了我想要实现的目标。它过于复杂,看起来编译器优化器比我想象的要聪明得多

// Log "function"
template <int N>
struct LOG
{
    static const int value = LOG<N/2>::value + 1;
};
template<>
struct LOG<0>
{
    static const int value = 0;
};

// pow "function"
template <int N>
struct POW
{
    static const int value = POW<N-1>::value * 2;
};
template<>
struct POW<1>
{
    static const int value = 2;
};

template<>
struct POW<0>
{
    static const int value = 1;
};

// Pair <key, value> to be a payload in a type list
template<int k, char v>
struct Pair
{
    static const int key = k;
    static const int value = v;
};

// type list manipulator - access n-th element
template <size_t, class...> struct element;
template <class TT, class...TTs>
struct element<0, TT, TTs...>
{
    typedef TT type;
};
template <size_t K, class TT, class...TTs>
struct element<K, TT, TTs...>
{
    typedef typename element<K-1, TTs...>::type type;
};

template<class... Ts>
struct V;

// Binary split search algorithm (pure templatized)
template<class T, class... Ts>
struct V<T, Ts...> : private V<Ts...>
{
    template<size_t N = sizeof...(Ts), size_t level = LOG<sizeof...(Ts)+1>::value>
    struct impl
    {
        template<size_t IDX>
        inline static char search_impl(size_t n)
        {
            using namespace std;
            static const int depth = LOG<N>::value;
            static const int layer = depth - level;
            static const int key   = element<IDX, T, Ts...>::type::key;
            static const size_t left_idx  = IDX - ( N / POW<layer + 2>::value + 1);
            static const size_t right_idx =
                IDX + ( N / POW<layer + 2>::value + 1) > sizeof...(Ts) ?
                sizeof...(Ts) :
                IDX + ( N / POW<layer + 2>::value + 1);             

            //std::cout << setfill('*') << setw(layer) << ' '
            //    << "Level:" << level << " of:" << depth << std::endl
            //    << std::setw(layer) << ' ' 
            //    << "IDX/val/layer/POW/level: "
            //    << " " << IDX
            //    << "/" << key
            //    << "/" << layer
            //    << "/" << POW<layer>::value
            //    << "/" << level
            //    << "/" << left_idx
            //    << "/" << right_idx
            //    << std::endl;
            if ( n < key )
                return V<T, Ts...>::impl<N, level-1>::template search_impl<left_idx>(n);
            else
                return V<T, Ts...>::impl<N, level-1>::template search_impl<right_idx>(n);       
        }

    };

    template<size_t N>
    struct impl<N,1>
    {
        template<size_t IDX>
        inline static char search_impl(size_t n)
        {
            static const int key   = element<IDX, T, Ts...>::type::key;
            static const char value1 = element<IDX-1, T, Ts...>::type::value;
            static const char value2 = element<IDX, T, Ts...>::type::value;
            if ( n < key )
            {
                //std::cout << " *" << value1 << ' '  << IDX << std::endl;
                return value1;
            } else {
                //std::cout << " *" << value2 << ' '  << IDX << std::endl;
                return value2;
            }
        }
    };

    static void print()
    {
        std::cout << typeid(T).name() << ' ' << T::key << ' ' << (char)T::value << std::endl;
        V<Ts...>::print();
    }
    static char search(size_t n)
    {
        static const size_t level = LOG<sizeof...(Ts)+1>::value;
        static const size_t N = sizeof...(Ts);
        static const int height = LOG<N>::value;
        static const size_t root_idx = N / 2 + 1;
        static const int key = element<root_idx, T, Ts...>::type::key;
        //std::cout << "Level:" << level << " of:" << height << std::endl
        //    << "IDX/val: "
        //    << " " << root_idx
        //    << "/" << input[root_idx]
        //    << std::endl;

        static const size_t left_idx  = root_idx - ( N / POW<2>::value + 1);
        static const size_t right_idx = root_idx + ( N / POW<2>::value + 1);

        if( n < key)
            return V<T, Ts...>::impl<N, level-1>::template search_impl<left_idx>(n);
        else
            return V<T, Ts...>::impl<N, level-1>::template search_impl<right_idx>(n);
    }
};

template<>
struct V<>
{
    static void print()
    {}
};

int main(int argc, char *argv[])
{
    int i = std::stoi(argv[1]);

    typedef V<
    Pair<  0x1,'a'>,
    Pair< 0x11,'b'>,
    Pair< 0x21,'c'>,
    Pair< 0x31,'d'>,
    Pair< 0x41,'e'>,
    Pair< 0x51,'f'>,
    Pair< 0x61,'g'>,
    Pair< 0x71,'h'>,
    Pair< 0x81,'i'>,
    Pair< 0x91,'j'>,
    Pair<0x101,'k'>,
    Pair<0x111,'l'>,
    Pair<0x121,'m'>,
    Pair<0x131,'n'>,
    Pair<0x141,'o'>
    > TV;

    std::cout << (char)TV::search(i) << std::endl;

    return 0;
};
//日志“函数”
模板
结构日志
{
静态常量int value=LOG::value+1;
};
模板
结构日志
{
静态常量int值=0;
};
//pow“功能”
模板
结构功率
{
静态常量int value=POW::value*2;
};
模板
结构功率
{
静态常数int值=2;
};
模板
结构功率
{
静态常数int值=1;
};
//配对为类型列表中的有效负载
模板
结构对
{
静态常数int key=k;
静态常数int值=v;
};
//类型列表操纵器-访问第n个元素
模板结构元素;
模板
结构元素
{
typedef-TT型;
};
模板
结构元素
{
typedef typename元素::type类型;
};
模板
结构V;
//二进制分割搜索算法(纯模板化)
模板
结构V:private V
{
模板
结构impl
{
模板
内联静态字符搜索\u impl(大小\u t n)
{
使用名称空间std;
静态常量int depth=LOG::value;
静态常量int layer=深度级别;
静态常量int key=element::type::key;
静态常量大小\u t left\u idx=idx-(N/POW::value+1);
静态常量大小\u t右\u idx=
IDX+(N/POW::value+1)>大小…(Ts)?
尺寸…(Ts):
IDX+(N/POW::value+1);

//你这样做的动机是什么?我想你可以写一个模板。是什么阻止你写模板?如果你来这里期待一个代码样本,你可能找错了方向。这个网站不专门从事代码实现
constexpr std::pair<int,char const *> tab[] 
{
    { 2,"apple" },
    { 5,"pear" },
    { 9,"orange" },
    { 14,"banana" },
    { 20,"plum" },
    { 20 + 1,nullptr }
};   
// Log "function"
template <int N>
struct LOG
{
    static const int value = LOG<N/2>::value + 1;
};
template<>
struct LOG<0>
{
    static const int value = 0;
};

// pow "function"
template <int N>
struct POW
{
    static const int value = POW<N-1>::value * 2;
};
template<>
struct POW<1>
{
    static const int value = 2;
};

template<>
struct POW<0>
{
    static const int value = 1;
};

// Pair <key, value> to be a payload in a type list
template<int k, char v>
struct Pair
{
    static const int key = k;
    static const int value = v;
};

// type list manipulator - access n-th element
template <size_t, class...> struct element;
template <class TT, class...TTs>
struct element<0, TT, TTs...>
{
    typedef TT type;
};
template <size_t K, class TT, class...TTs>
struct element<K, TT, TTs...>
{
    typedef typename element<K-1, TTs...>::type type;
};

template<class... Ts>
struct V;

// Binary split search algorithm (pure templatized)
template<class T, class... Ts>
struct V<T, Ts...> : private V<Ts...>
{
    template<size_t N = sizeof...(Ts), size_t level = LOG<sizeof...(Ts)+1>::value>
    struct impl
    {
        template<size_t IDX>
        inline static char search_impl(size_t n)
        {
            using namespace std;
            static const int depth = LOG<N>::value;
            static const int layer = depth - level;
            static const int key   = element<IDX, T, Ts...>::type::key;
            static const size_t left_idx  = IDX - ( N / POW<layer + 2>::value + 1);
            static const size_t right_idx =
                IDX + ( N / POW<layer + 2>::value + 1) > sizeof...(Ts) ?
                sizeof...(Ts) :
                IDX + ( N / POW<layer + 2>::value + 1);             

            //std::cout << setfill('*') << setw(layer) << ' '
            //    << "Level:" << level << " of:" << depth << std::endl
            //    << std::setw(layer) << ' ' 
            //    << "IDX/val/layer/POW/level: "
            //    << " " << IDX
            //    << "/" << key
            //    << "/" << layer
            //    << "/" << POW<layer>::value
            //    << "/" << level
            //    << "/" << left_idx
            //    << "/" << right_idx
            //    << std::endl;
            if ( n < key )
                return V<T, Ts...>::impl<N, level-1>::template search_impl<left_idx>(n);
            else
                return V<T, Ts...>::impl<N, level-1>::template search_impl<right_idx>(n);       
        }

    };

    template<size_t N>
    struct impl<N,1>
    {
        template<size_t IDX>
        inline static char search_impl(size_t n)
        {
            static const int key   = element<IDX, T, Ts...>::type::key;
            static const char value1 = element<IDX-1, T, Ts...>::type::value;
            static const char value2 = element<IDX, T, Ts...>::type::value;
            if ( n < key )
            {
                //std::cout << " *" << value1 << ' '  << IDX << std::endl;
                return value1;
            } else {
                //std::cout << " *" << value2 << ' '  << IDX << std::endl;
                return value2;
            }
        }
    };

    static void print()
    {
        std::cout << typeid(T).name() << ' ' << T::key << ' ' << (char)T::value << std::endl;
        V<Ts...>::print();
    }
    static char search(size_t n)
    {
        static const size_t level = LOG<sizeof...(Ts)+1>::value;
        static const size_t N = sizeof...(Ts);
        static const int height = LOG<N>::value;
        static const size_t root_idx = N / 2 + 1;
        static const int key = element<root_idx, T, Ts...>::type::key;
        //std::cout << "Level:" << level << " of:" << height << std::endl
        //    << "IDX/val: "
        //    << " " << root_idx
        //    << "/" << input[root_idx]
        //    << std::endl;

        static const size_t left_idx  = root_idx - ( N / POW<2>::value + 1);
        static const size_t right_idx = root_idx + ( N / POW<2>::value + 1);

        if( n < key)
            return V<T, Ts...>::impl<N, level-1>::template search_impl<left_idx>(n);
        else
            return V<T, Ts...>::impl<N, level-1>::template search_impl<right_idx>(n);
    }
};

template<>
struct V<>
{
    static void print()
    {}
};

int main(int argc, char *argv[])
{
    int i = std::stoi(argv[1]);

    typedef V<
    Pair<  0x1,'a'>,
    Pair< 0x11,'b'>,
    Pair< 0x21,'c'>,
    Pair< 0x31,'d'>,
    Pair< 0x41,'e'>,
    Pair< 0x51,'f'>,
    Pair< 0x61,'g'>,
    Pair< 0x71,'h'>,
    Pair< 0x81,'i'>,
    Pair< 0x91,'j'>,
    Pair<0x101,'k'>,
    Pair<0x111,'l'>,
    Pair<0x121,'m'>,
    Pair<0x131,'n'>,
    Pair<0x141,'o'>
    > TV;

    std::cout << (char)TV::search(i) << std::endl;

    return 0;
};