gpt4 book ai didi

c++ - 如何提高该模式所需的模板递归深度?

转载 作者:可可西里 更新时间:2023-11-01 18:31:26 27 4
gpt4 key购买 nike

我一直在我的代码中使用这个 SO 问题中描述的模式来制作各种编译时注册列表:C++ type registration at compile time trick

例如,如果你有一堆 lua 回调函数并且你不想忘记将它们注册到某个 lua 状态,你可以使用一个宏来声明它们,该宏将知道它们的名称和函数指针的模板类型放入一个列表,然后你有一个单行代码,它注册了所有的功能。

此技术的局限性(如 SO 答案中所述)是,如果您有 n列表中的项目,它需要模板递归深度O(n)评估。这并不理想,实际上我已经有不少 lua 回调函数了......

我曾相信O(n)由于各种原因,递归深度是不可避免的,但是正如我最近在这个(未发布的)答案中从 Yakk 那里了解到的,我天真地认为需要一些基本的东西 O(n)实际上可以在 O(log n) 中完成深度。 Switch statement variadic template expansion

特别是没有理由再要求所涉及的数据结构需要 O(log n)他们操作的模板深度。

我不确定的部分是 Rank诡计。从引用代码来看,这个模板

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

template <>
struct Rank<0> {};

是关键成分。虽然它在模板深度方面很昂贵——实例化 Rank<N>需要模板深度 N .它具有的重要属性是,如果函数 f被定义为使用许多不同等级类型重载,重载决议总是选择最大等级的重载,因为那是“最派生的实例”。例如。如果我们有这段代码:

bool f(Rank<0>) { return false; }
int f(Rank<1>) { return 0; }
float f(Rank<2>) { return 0; }
double f(Rank<3>) { return 0; }

那么在代码中的任何一点,情况总是如此,decltype(f(Rank<100>{}))具有等于​​最近定义的重载的返回值的类型。 IE。这些断言通过

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:");

有没有不需要模板递归深度的方法来做到这一点 O(n)

也许为函数重载使用更多、精心选择的参数(?)

最佳答案

为了避免类型错误:

template instantiation depth exceeds maximum of 900 (use -ftemplate-depth= to increase the maximum) instantiating 'struct Rank<1148u>'

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

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

你可能还有一个 helper :

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

然后

template struct Instantiate<Rank, 2000, 250>; // Rank<2000> is now instantiated.

关于c++ - 如何提高该模式所需的模板递归深度?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32241555/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com