【问题标题】:boost tuple: increasing maximum number of elementsboost tuple:增加最大元素数
【发布时间】:2011-06-21 12:24:54
【问题描述】:

boost tuple documentation 说:

当前版本支持元组 有 0-10 个元素。如有必要, 上限可以增加到, 比如说,几十个元素。

但是,我找不到它说明如何执行此操作的位置。

我希望元组有 BOOST_MPL_LIMIT_VECTOR_SIZE 元素(默认为 20)。这是因为我在 mpl::vectorsboost::tuples 之间进行映射,并且希望所有容器都具有相同数量的元素。

【问题讨论】:

  • 不使用 C++0x 我们不能声明可变参数模板参数。因此,实现可以通过使用宏来创建元组定义,这将有助于“增加”上限。但是,我认为目前不可能。
  • @FrEEzE2046 嗯?有什么不可能的? - 文档说可以提高上限?
  • 我的阅读是,虽然如@FrEEzE2046 的回答中所述,这理论上是可能的,但目前的代码不支持> 10 个元素。如果这对您来说是一个阻碍,您可以编辑它以自己添加更多参数。我认为他们的意思是如果你想要超过几十个,它会变得太混乱而无法考虑(或编译?)。
  • 奇怪的是,MSVS10 不支持可变参数模板,因此他们使用了一种相当不正当的“预处理器加上重复的无保护包含”的巫术来自动创建大量非可变参数模板来伪造 C++0x 元组(见ASTL#1, about 1500s in)。显然 Boost 选择了一种不同的、不那么晦涩且不太灵活的方式来硬编码元组模板。

标签: c++ boost-tuples


【解决方案1】:

元组类的声明方式如下:

// - tuple forward declaration -----------------------------------------------
template <
  class T0 = null_type, class T1 = null_type, class T2 = null_type,
  class T3 = null_type, class T4 = null_type, class T5 = null_type,
  class T6 = null_type, class T7 = null_type, class T8 = null_type,
  class T9 = null_type>
class tuple;

因此,它的模板参数计数设置为上限 10。但是,将来(C++0x)可能会这样声明:

template<class... Params> class tuple;

所以,我认为目前在实践中不可能提高上限。可以通过以下方式实现:

#define VARIADIC_PARAMS_DEFVAL0(type_name, value)
#define VARIADIC_PARAMS_DEFVAL1(type_name, value)   type_name##0 = value
#define VARIADIC_PARAMS_DEFVAL2(type_name, value)   VARIADIC_PARAMS_DEFVAL1(type_name, value), type_name##1 = value
#define VARIADIC_PARAMS_DEFVAL3(type_name, value)   VARIADIC_PARAMS_DEFVAL2(type_name, value), type_name##2 = value
#define VARIADIC_PARAMS_DEFVAL4(type_name, value)   VARIADIC_PARAMS_DEFVAL3(type_name, value), type_name##3 = value
#define VARIADIC_PARAMS_DEFVAL5(type_name, value)   VARIADIC_PARAMS_DEFVAL4(type_name, value), type_name##4 = value
#define VARIADIC_PARAMS_DEFVAL6(type_name, value)   VARIADIC_PARAMS_DEFVAL5(type_name, value), type_name##5 = value
#define VARIADIC_PARAMS_DEFVAL7(type_name, value)   VARIADIC_PARAMS_DEFVAL6(type_name, value), type_name##6 = value
#define VARIADIC_PARAMS_DEFVAL8(type_name, value)   VARIADIC_PARAMS_DEFVAL7(type_name, value), type_name##7 = value
#define VARIADIC_PARAMS_DEFVAL9(type_name, value)   VARIADIC_PARAMS_DEFVAL8(type_name, value), type_name##8 = value
#define VARIADIC_PARAMS_DEFVAL10(type_name, value)  VARIADIC_PARAMS_DEFVAL9(type_name, value), type_name##9 = value
// ...
#define VARIADIC_PARAMS_DEFVAL100(type_name, value) VARIADIC_PARAMS_DEFVAL99(type_name, value), type_name##99 = value
#define VARIADIC_PARAMS_DEFVAL(type_name, value, n) VARIADIC_PARAMS_DEFVAL##n(type_name, value)

#define VARIADIC_MACRO_INVOKE0(macro)    macro(0)
#define VARIADIC_MACRO_INVOKE1(macro)    VARIADIC_MACRO_INVOKE0(macro); macro(1)
#define VARIADIC_MACRO_INVOKE2(macro)    VARIADIC_MACRO_INVOKE1(macro); macro(2)
#define VARIADIC_MACRO_INVOKE3(macro)    VARIADIC_MACRO_INVOKE2(macro); macro(3)
#define VARIADIC_MACRO_INVOKE4(macro)    VARIADIC_MACRO_INVOKE3(macro); macro(4)
#define VARIADIC_MACRO_INVOKE5(macro)    VARIADIC_MACRO_INVOKE4(macro); macro(5)
#define VARIADIC_MACRO_INVOKE6(macro)    VARIADIC_MACRO_INVOKE5(macro); macro(6)
#define VARIADIC_MACRO_INVOKE7(macro)    VARIADIC_MACRO_INVOKE6(macro); macro(7)
#define VARIADIC_MACRO_INVOKE8(macro)    VARIADIC_MACRO_INVOKE7(macro); macro(8)
#define VARIADIC_MACRO_INVOKE9(macro)    VARIADIC_MACRO_INVOKE8(macro); macro(9)
#define VARIADIC_MACRO_INVOKE10(macro)   VARIADIC_MACRO_INVOKE9(macro); macro(10)
// ...
#define VARIADIC_MACRO_INVOKE100(macro)  VARIADIC_MACRO_INVOKE99(macro); macro(100)
#define VARIADIC_MACRO_INVOKE(macro, n)  VARIADIC_MACRO_INVOKE##n(macro)

#define TUPPLE_UPPER_LIMIT      50

#define FORWARD_DECLARE_TUPPLE(N)                       \
template<VARIADIC_PARAMS_DEFVAL(class, null_type, N)    \
class tuple;

FS_VARIADIC_MACRO_INVOKE(FORWARD_DECLARE_TUPPLE, TUPPLE_UPPER_LIMIT);

【讨论】:

  • 哦,我明白了,我想知道他们为什么这样定义它,而不是template &lt;BOOST_PP_ENUM_PARAMS(TUPLE_MAX_SIZE, class T)&gt; struct tuple;?谢谢
  • 也许是为了减少boost模块之间的依赖?
  • 这可能会导致内部库问题。如果他们会在其他标题中使用元组对象,并且在重新定义“上限宏”后将它们包含在内,则可能会破坏代码。
  • 顺便说一句,MPL 和 Variant 模块已经是这种情况了。
  • @Matthieu M. - 是的,但正如我所说:总的来说,这并没有错或不好,但您需要知道自己在做什么以及在哪里做。
【解决方案2】:

好消息。找到答案,它只是使用宏重新定义最大参数。 boost 中的库 FUSION 重新定义了元组。按照以下步骤,你可以轻松扩展元组参数

  1. 在包含任何元组文件之前定义 FUSION_MAX_VECTOR_SIZE
  2. 包含 fusion 或 TR1 版本的元组头文件,而不是普通的元组头

     #define FUSION_MAX_VECTOR_SIZE 50
     #include <boost/tr1/tuple.hpp>
    

为了更好的理解上面的代码,可以参考头文件“boost/tr1/tuple.hpp”

在文件中,它有另一个“BOOST_TR1_USE_OLD_TUPLE”来引用旧的元组实现。

在融合的元组实现“boost/fusion/tuple/tuple.hpp”中,还有另一个宏。 “BOOST_FUSION_DONT_USE_PREPROCESSED_FILES”。如果没有定义,库将使用预先创建的头文件,最大参数为50。如果您需要更多,我相信您可以将这个宏定义为true。从代码来看,应该可以有更多的参数,虽然我还没有真正尝试过。因为 50 对我来说已经足够了 ;)

如果你只是定义FUSION_MAX_VECTOR_SIZE并且你需要超过50个参数,你会发现另一个问题。你必须为向量模板拿出你自己的头文件,而不是使用现有的流程头文件。除了以下代码,您还需要定义宏“BOOST_FUSION_DONT_USE_PREPROCESSED_FILES”来排除经过处理的头文件

#if (FUSION_MAX_VECTOR_SIZE > 50)

#include <boost/fusion/container/vector/vector50.hpp>

namespace boost 
{ 
namespace mpl 
{
#define BOOST_PP_ITERATION_PARAMS_1 (3,(51, FUSION_MAX_VECTOR_SIZE, <boost/mpl/vector/aux_/numbered.hpp>))
#include BOOST_PP_ITERATE()
}

namespace fusion
{
    struct vector_tag;
    struct fusion_sequence_tag;
    struct random_access_traversal_tag;

    // expand vector51 to max
    #define BOOST_PP_FILENAME_1 <boost/fusion/container/vector/detail/vector_n.hpp>
    #define BOOST_PP_ITERATION_LIMITS (51, FUSION_MAX_VECTOR_SIZE)
    #include BOOST_PP_ITERATE()
}
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多