12

The boost tuple documentation says:

The current version supports tuples with 0-10 elements. If necessary, the upper limit can be increased up to, say, a few dozen elements.

However, I could not find where it says how to do this.

I would like the tuple to have BOOST_MPL_LIMIT_VECTOR_SIZE elements (20 by default). This is because I am mapping between mpl::vectors and boost::tuples and would like all the containers to have the same number of elements.

Tom
  • 5,219
  • 2
  • 29
  • 45
  • Without using C++0x we can't declare variadic template parameters. So, the implemention could create the tuple definitions by using macros, which would help to "increase" the upper limit. However, I don't think it's possible at the moment. – 0xbadf00d Jun 21 '11 at 12:34
  • @FrEEzE2046 huh? Whats impossible? - The documentation says it is possible to increase the upper limit? – Tom Jun 21 '11 at 12:40
  • 1
    my reading is that while this is **theoretically** possible as noted in @FrEEzE2046's answer, the code as it stands does not support > 10 elements. You could edit it to add more parameters yourself if this is a showstopper for you. I think they mean if you wanted more than a few dozen, it would get too messy to contemplate (or compile?). – Steve Townsend Jun 21 '11 at 13:06
  • Curiously, MSVS10 doesn't support variadic templates, so they employed a rather perverse "preprocessor plus repeated unguarded inclusion" voodoo to automatically create a large number of non-variadic templates to fake C++0x tuples (see [ASTL#1, about 1500s in](http://channel9.msdn.com/Shows/Going+Deep/C9-Lectures-Stephan-T-Lavavej-Advanced-STL-1-of-n)). Apparently Boost chose a different, less obscure and less flexible way to hardcode tuple templates. – Kerrek SB Jun 21 '11 at 14:45

2 Answers2

5

Good news. Find the answer, it is just use the macro to re-define the max parameters. The library FUSION in boost re-define the tuple. Follow the following steps, you can easily extend the tuple parameters

  1. define the FUSION_MAX_VECTOR_SIZE before including any tuple file
  2. include the fusion or TR1 version tuple header file instead of the normal tuple header

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

To understand the above code better, you can refer to the header file "boost/tr1/tuple.hpp"

in the file, it has another "BOOST_TR1_USE_OLD_TUPLE" to refer to the old tuple implementation.

in the fusion's tuple implementation "boost/fusion/tuple/tuple.hpp", there is another macro. "BOOST_FUSION_DONT_USE_PREPROCESSED_FILES". if it is not defined, the library will use the pre-created header file, the maximum parameter are 50. if you need more, I believe you can just define this macro to true. From the code, it should be OK to have more parameters although I haven't really try it out. because 50 to me is far more enough ;)

find another issue if you just define FUSION_MAX_VECTOR_SIZE and you need the parameters are more than 50. you have to come out your own header file for the vector template instead of using the existing process header file. besides the following code, you also need define the macro "BOOST_FUSION_DONT_USE_PREPROCESSED_FILES" to exclude the proprocessed header file

#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()
}
}
Shen liang
  • 1,385
  • 15
  • 15
5

The tuple class is declared in the following way:

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

Thus, its template parameter count is set to a upper limit of 10. However, it would be possible in the future (C++0x) to declare it like that:

template<class... Params> class tuple;

So, I don't think it's currently possible to increase the upper limit in practice. It would been possible in the following way:

#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);
0xbadf00d
  • 17,405
  • 15
  • 67
  • 107
  • Oh, I see, I wonder why they defined it like that, rather than by `template struct tuple;`? Thanks – Tom Jun 21 '11 at 12:59
  • Maybe to reduce dependency between boost modules? – RedX Jun 21 '11 at 13:02
  • 1
    It could lead to internal library problems. If they would use tuple objects in other headers and you include them after you've redefined the "upper-limit-macro" you could break the code. – 0xbadf00d Jun 21 '11 at 13:08
  • this is already the case with the MPL and the Variant modules, by the way. – Matthieu M. Jun 21 '11 at 13:31
  • @Matthieu M. - Right, but as I said: It's not wrong or bad in general, but you need to know what you're doing and where you're doing it. – 0xbadf00d Jun 21 '11 at 13:56