Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/144.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++_Templates_C++11_Recursion_C++14 - Fatal编程技术网

C++ 如何提高此模式所需的模板递归深度?

C++ 如何提高此模式所需的模板递归深度?,c++,templates,c++11,recursion,c++14,C++,Templates,C++11,Recursion,C++14,在我的代码中,我一直在使用这个SO问题中描述的模式来创建各种编译时注册列表: 例如,如果您有一组lua回调函数,并且您不想忘记将它们注册到某个lua状态,那么您可以使用一个宏来声明它们,该宏将知道它们的名称和函数指针的模板类型放入一个列表中,然后您将有一个一行程序来注册所有函数 此技术的一个限制(如SO答案中所述)是,如果列表中有n项,则需要模板递归深度O(n)进行评估。这并不理想,实际上我已经有很多lua回调函数了 我曾认为,由于各种原因,O(n)递归深度是不可避免的,然而,正如我最近在这个(

在我的代码中,我一直在使用这个SO问题中描述的模式来创建各种编译时注册列表:

例如,如果您有一组lua回调函数,并且您不想忘记将它们注册到某个lua状态,那么您可以使用一个宏来声明它们,该宏将知道它们的名称和函数指针的模板类型放入一个列表中,然后您将有一个一行程序来注册所有函数

此技术的一个限制(如SO答案中所述)是,如果列表中有
n
项,则需要模板递归深度
O(n)
进行评估。这并不理想,实际上我已经有很多lua回调函数了

我曾认为,由于各种原因,
O(n)
递归深度是不可避免的,然而,正如我最近在这个(未解释的)答案中从雅克那里学到的,我天真地认为需要
O(n)
的一些基本事情实际上可以在
O(logn)
深度中完成

特别是,不再有任何理由认为所涉及的数据结构需要
O(logn)
模板深度来进行操作

我不确定的部分是
Rank
技巧。根据引用的代码,此模板

template <int N>
struct Rank : Rank<N - 1> {};

template <>
struct Rank<0> {};
然后,在代码中的任何一点,
decltype(f(Rank{}))
的type都等于最近定义的重载的返回值。也就是说,这些断言是通过的

bool f(Rank<0>) { return false; }
static_assert(std::is_same<bool, decltype(f(Rank<100>{}))>::value, "D:");
int f(Rank<1>) { return 0; }
static_assert(std::is_same<int, decltype(f(Rank<100>{}))>::value, "D:");
float f(Rank<2>) { return 0; }
static_assert(std::is_same<float, decltype(f(Rank<100>{}))>::value, "D:");
double f(Rank<3>) { return 0; }
static_assert(std::is_same<double, decltype(f(Rank<100>{}))>::value, "D:");
boolf(Rank){返回false;}
静态断言(std::is_same::value,“D:”);
int f(秩){返回0;}
静态断言(std::is_same::value,“D:”);
浮点f(秩){返回0;}
静态断言(std::is_same::value,“D:”);
双f(秩){返回0;}
静态断言(std::is_same::value,“D:”);
有没有一种方法不需要模板递归深度
O(n)


也许可以为函数重载(?)

使用更多仔细选择的参数,以避免类型错误:

模板实例化深度超过最大值900(使用-ftemplate depth=增加最大值)实例化“struct Rank”

在不增加全局最大模板深度的情况下,您可以实例化中间模板:

// To allow instantiation of Rank<1000> with template-depth at 256
template struct Rank<250>;
template struct Rank<500>;
template struct Rank<750>;
template struct Rank<1000>;
//允许模板深度为256的列组实例化
模板结构等级;
模板结构等级;
模板结构等级;
模板结构等级;
您还可能有一个助手:

namespace detail
{

    template <template <std::size_t> class C,
              typename Seq,
              std::size_t BlockSize>
    struct Instantiate_Impl;

    template <template <std::size_t> class C,
              std::size_t... Is,
              std::size_t BlockSize>
    struct Instantiate_Impl<C, std::index_sequence<Is...>, BlockSize>
    {
        std::tuple<C<(Is * BlockSize)>...> dummy;
    };
}

template <template <std::size_t> class C,
          std::size_t N,
          std::size_t BlockSize = 250>
struct Instantiate :
    detail::Instantiate_Impl<C,
                             std::make_index_sequence<1 + N / BlockSize>,
                             BlockSize>
{};
名称空间详细信息
{
模板
结构实例化_Impl;
模板
结构实例化\u Impl
{
std::元组虚拟;
};
}
模板
结构实例化:
细节::实例化_Impl
{};
然后

template struct Instantiate<Rank, 2000, 250>; // Rank<2000> is now instantiated.
模板结构实例化;//等级现在被实例化。

您是否测量了所采取的措施?作为总时间的一部分,它对你有意义吗?或者这是出于“学术”的兴趣?@TonyD:我不太关心时间,我只关心达到最大模板递归深度(通常为256)并消除编译过程错误。我在一些地方使用这种模式——如果限制非常大,比如说,以百万计,而不是以数百计,那就太好了,所以我不必跟踪这些东西。在“学术”兴趣之外,获得它比获得
O(logn)
更重要。这项工作的关键是
Rank
是所有
M
Rank
的直接或间接基类。您不能真正避免线性实例化。@ChrisBeck我提到运行时性能,因为您表面上是在使用编译时技术,而不是让宏使用注册单个函数的构造函数创建静态对象,或将名称和函数指针添加到标准库容器,以进行post-
main()
注册。您正在调用哪种注册函数可以更好地处理编译时(函数指针)类型信息?也许如果我们能看到您最终拨打的lua注册码,我们会感激/评估您的需求或好处。。。。
template struct Instantiate<Rank, 2000, 250>; // Rank<2000> is now instantiated.