3

Trying to create boilerplate code for a huge struct with more than 64 members and the BOOST_FUSION_ADAPT_STRUCT macro but it fails to compile in VS2015 Update 3. I've tried to play with BOOST_FUSION_HAS_VARIADIC_VECTOR and BOOST_PP_LIMIT_TUPLE but no luck, I keep getting the same error if I add more than 64 members to BOOST_FUSION_ADAPT_STRUCT. Did not find any mention of limits the BOOST_FUSION_ADAPT_STRUCT has except when it is in C++03 mode. Am I missing something?

Live at Coliru

Code:

#include <boost/fusion/adapted/struct/adapt_struct.hpp>

struct Data
{
    int a01 = 1;
    int a02 = 1;
    int a03 = 1;
    int a04 = 1;
    int a05 = 1;
    int a06 = 1;
    int a07 = 1;
    int a08 = 1;
    int a09 = 1;
    int a10 = 1;
    int a11 = 1;
    int a12 = 1;
    int a13 = 1;
    int a14 = 1;
    int a15 = 1;
    int a16 = 1;
    int a17 = 1;
    int a18 = 1;
    int a19 = 1;
    int a20 = 1;
    int a21 = 1;
    int a22 = 1;
    int a23 = 1;
    int a24 = 1;
    int a25 = 1;
    int a26 = 1;
    int a27 = 1;
    int a28 = 1;
    int a29 = 1;
    int a30 = 1;
    int a31 = 1;
    int a32 = 1;
    int a33 = 1;
    int a34 = 1;
    int a35 = 1;
    int a36 = 1;
    int a37 = 1;
    int a38 = 1;
    int a39 = 1;
    int a40 = 1;
    int a41 = 1;
    int a42 = 1;
    int a43 = 1;
    int a44 = 1;
    int a45 = 1;
    int a46 = 1;
    int a47 = 1;
    int a48 = 1;
    int a49 = 1;
    int a50 = 1;
    int a51 = 1;
    int a52 = 1;
    int a53 = 1;
    int a54 = 1;
    int a55 = 1;
    int a56 = 1;
    int a57 = 1;
    int a58 = 1;
    int a59 = 1;
    int a60 = 1;
    int a61 = 1;
    int a62 = 1;
    int a63 = 1;
    int a64 = 1;
    int a65 = 1;
    int a66 = 1;
    int a67 = 1;
    int a68 = 1;
    int a69 = 1;
    int a70 = 1;
};

BOOST_FUSION_ADAPT_STRUCT(Data, a01, a02, a03, a04, a05, a06, a07, a08, a09, a10, a11, a12, a13, a14, a15, a16, a17,
                          a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32, a33, a34, a35, a36,
                          a37, a38, a39, a40, a41, a42, a43, a44, a45, a46, a47, a48, a49, a50, a51, a52, a53, a54, a55,
                          a56, a57, a58, a59, a60, a61, a62, a63/*, a64, a65, a66, a67, a68, a69, a70*/) // uncomment the a64 to get the error


int main()
{
    return 0;
}

MSVC errors:

1>consoleapplication23.cpp(119): warning C4003: not enough actual parameters for macro 'BOOST_PP_SEQ_ELEM_III' 1>consoleapplication23.cpp(119): error C2065: 'BOOST_PP_SEQ_ELEM_0': undeclared identifier 1>consoleapplication23.cpp(119): error C2146: syntax error: missing '>' before identifier 'BOOST_PP_TUPLE_TO_SEQ_a64' 1>consoleapplication23.cpp(119): error C2065: 'a01': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a02': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a03': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a04': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a05': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a06': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a07': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a08': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a09': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a10': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a11': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a12': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a13': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a14': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a15': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a16': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a17': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a18': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a19': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a20': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a21': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a22': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a23': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a24': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a25': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a26': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a27': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a28': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a29': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a30': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a31': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a32': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a33': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a34': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a35': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a36': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a37': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a38': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a39': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a40': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a41': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a42': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a43': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a44': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a45': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a46': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a47': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a48': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a49': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a50': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a51': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a52': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a53': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a54': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a55': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a56': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a57': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a58': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a59': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a60': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a61': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a62': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a63': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a64': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a65': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a66': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a67': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a68': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a69': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a70': undeclared identifier 1>consoleapplication23.cpp(116): error C2059: syntax error: ')' 1>consoleapplication23.cpp(119): error C2977: 'boost::fusion::traits::tag_of': too many template arguments 1> packages\boost.1.61.0.0\lib\native\include\boost\fusion\support\tag_of.hpp(71): note: see declaration of 'boost::fusion::traits::tag_of' 1>consoleapplication23.cpp(119): error C2913: explicit specialization; 'boost::fusion::traits::tag_of' is not a specialization of a class template 1>consoleapplication23.cpp(119): error C2913: explicit specialization; 'boost::fusion::traits::tag_of' is not a specialization of a class template 1>consoleapplication23.cpp(119): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int 1>consoleapplication23.cpp(119): error C2440: 'initializing': cannot convert from 'initializer list' to 'int' 1> consoleapplication23.cpp(119): note: The initializer contains too many elements 1>consoleapplication23.cpp(116): error C2059: syntax error: '(' 1>consoleapplication23.cpp(119): error C2065: 'BOOST_PP_SEQ_ELEM_0': undeclared identifier 1>consoleapplication23.cpp(119): error C2146: syntax error: missing '>' before identifier 'BOOST_PP_TUPLE_TO_SEQ_a64' 1>consoleapplication23.cpp(119): error C2065: 'a01': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a02': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a03': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a04': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a05': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a06': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a07': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a08': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a09': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a10': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a11': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a12': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a13': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a14': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a15': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a16': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a17': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a18': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a19': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a20': undeclared identifier 1>consoleapplication23.cpp(119): error C2065: 'a21': undeclared identifier 1>consoleapplication23.cpp(119): fatal error C1003: error count exceeds 100; stopping compilation

GCC errors:

main.cpp:80:1: error: macro "BOOST_PP_SEQ_ELEM_III" requires 2 arguments, but only 1 given a56, a57, a58, a59, a60, a61, a62, a63, a64, a65, a66, a67, a68, a69, a70) // uncomment the a64 to get the error ^ In file included from /usr/local/include/boost/preprocessor/seq/seq.hpp:16:0, from /usr/local/include/boost/fusion/adapted/struct/adapt_struct.hpp:20, from main.cpp:1: main.cpp:77:1: error: 'BOOST_PP_SEQ_ELEM_III' was not declared in this scope BOOST_FUSION_ADAPT_STRUCT(Data, a01, a02, a03, a04, a05, a06, a07, a08, a09, a10, a11, a12, a13, a14, a15, a16, a17, ^ In file included from /usr/local/include/boost/fusion/adapted/struct/adapt_struct.hpp:28:0, from main.cpp:1: main.cpp:77:1: error: template argument 1 is invalid BOOST_FUSION_ADAPT_STRUCT(Data, a01, a02, a03, a04, a05, a06, a07, a08, a09, a10, a11, a12, a13, a14, a15, a16, a17, ^ In file included from /usr/local/include/boost/preprocessor/seq/seq.hpp:16:0, from /usr/local/include/boost/fusion/adapted/struct/adapt_struct.hpp:20, from main.cpp:1: main.cpp:77:1: error: 'BOOST_PP_SEQ_ELEM_III' was not declared in this scope BOOST_FUSION_ADAPT_STRUCT(Data, a01, a02, a03, a04, a05, a06, a07, a08, a09, a10, a11, a12, a13, a14, a15, a16, a17, ^ In file included from /usr/local/include/boost/fusion/adapted/struct/adapt_struct.hpp:28:0, from main.cpp:1: main.cpp:77:1: error: template argument 1 is invalid BOOST_FUSION_ADAPT_STRUCT(Data, a01, a02, a03, a04, a05, a06, a07, a08, a09, a10, a11, a12, a13, a14, a15, a16, a17, ^ In file included from /usr/local/include/boost/preprocessor/control/if.hpp:18:0, from /usr/local/include/boost/fusion/adapted/struct/adapt_struct.hpp:17, from main.cpp:1: main.cpp:77:1: error: 'BOOST_PP_IIF_0' does not name a type BOOST_FUSION_ADAPT_STRUCT(Data, a01, a02, a03, a04, a05, a06, a07, a08, a09, a10, a11, a12, a13, a14, a15, a16, a17, ^ In file included from /usr/local/include/boost/preprocessor/seq/seq.hpp:16:0, from /usr/local/include/boost/fusion/adapted/struct/adapt_struct.hpp:20, from main.cpp:1: main.cpp:77:1: error: 'BOOST_PP_SEQ_ELEM_III' was not declared in this scope BOOST_FUSION_ADAPT_STRUCT(Data, a01, a02, a03, a04, a05, a06, a07, a08, a09, a10, a11, a12, a13, a14, a15, a16, a17, ^ In file included from /usr/local/include/boost/fusion/adapted/struct/adapt_struct.hpp:28:0, from main.cpp:1: main.cpp:77:1: error: template argument 1 is invalid BOOST_FUSION_ADAPT_STRUCT(Data, a01, a02, a03, a04, a05, a06, a07, a08, a09, a10, a11, a12, a13, a14, a15, a16, a17, ^ In file included from /usr/local/include/boost/preprocessor/seq/seq.hpp:16:0, from /usr/local/include/boost/fusion/adapted/struct/adapt_struct.hpp:20, from main.cpp:1: main.cpp:77:1: error: 'BOOST_PP_SEQ_ELEM_III' was not declared in this scope BOOST_FUSION_ADAPT_STRUCT(Data, a01, a02, a03, a04, a05, a06, a07, a08, a09, a10, a11, a12, a13, a14, a15, a16, a17, ^ In file included from /usr/local/include/boost/fusion/adapted/struct/adapt_struct.hpp:28:0, from main.cpp:1: main.cpp:77:1: error: template argument 1 is invalid BOOST_FUSION_ADAPT_STRUCT(Data, a01, a02, a03, a04, a05, a06, a07, a08, a09, a10, a11, a12, a13, a14, a15, a16, a17, ^ In file included from /usr/local/include/boost/preprocessor/seq/seq.hpp:16:0, from /usr/local/include/boost/fusion/adapted/struct/adapt_struct.hpp:20, from main.cpp:1: main.cpp:77:1: error: 'BOOST_PP_SEQ_ELEM_III' was not declared in this scope BOOST_FUSION_ADAPT_STRUCT(Data, a01, a02, a03, a04, a05, a06, a07, a08, a09, a10, a11, a12, a13, a14, a15, a16, a17, ^ In file included from /usr/local/include/boost/fusion/adapted/struct/adapt_struct.hpp:28:0, from main.cpp:1: main.cpp:77:1: error: template argument 1 is invalid BOOST_FUSION_ADAPT_STRUCT(Data, a01, a02, a03, a04, a05, a06, a07, a08, a09, a10, a11, a12, a13, a14, a15, a16, a17, ^

g++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp && ./a.out

kreuzerkrieg
  • 3,009
  • 3
  • 28
  • 59

3 Answers3

2

It looks like BOOST_FUSION_ADAPT_STRUCT has two parameters per class element, type and name. MSVC only supports 127 macro parameters while the Standard recommends 255. This explains why the 64'th element, requiring 128 macro parameters, fails to compile on MSVC++.

MSalters
  • 173,980
  • 10
  • 155
  • 350
  • 1
    `BOOST_FUSION_ADAPT_STRUCT` only needs 1 parameter per class element, its name. see http://www.boost.org/doc/libs/1_61_0/libs/fusion/doc/html/fusion/adapted/adapt_struct.html – m.s. Aug 15 '16 at 11:02
  • 1
    Since Coliru fails on the same 64th element I guess CGG has the same limitation, or, more likely, there is something in Boost Fusion that limits it – kreuzerkrieg Aug 15 '16 at 11:08
  • @m.s.: In which case it's using `Boost.TypeOf` to figure out the type. I'll bet that gets you macro parameters 64-128 during macro expansion. – MSalters Aug 15 '16 at 11:08
  • @kreuzerkrieg maybe `BOOST_PP_LIMIT_VARIADIC` causes this? http://www.boost.org/doc/libs/1_61_0/libs/preprocessor/doc/ref/limit_variadic.html – m.s. Aug 15 '16 at 11:10
  • 3
    The limitation seems to be in Boost.Preprocessor, especifically in the BOOST_PP_VARIADIC_TO_SEQ macro. [Simple test](http://rextester.com/ZPLMB46692). – llonesmiz Aug 15 '16 at 11:11
  • @jv_: It's possible the limitations are two sides of one coin: Boost may have set its limit so that it compiles on MSVC++. – MSalters Aug 15 '16 at 11:15
  • @jv_, gotcha! # define BOOST_PP_TUPLE_TO_SEQ_64(e0, e1, ...(e63). looks like you are right. Any know workaround for it? – kreuzerkrieg Aug 15 '16 at 11:25
  • @MSalters, I didnt find any mention of any limit of variadics size in MSVC – kreuzerkrieg Aug 15 '16 at 11:26
  • 2
    Changing BOOST_PP_TUPLE_TO_SEQ and BOOST_PP_VARIADIC_SIZE seems to [make it work for 64 elements](http://rextester.com/JPO75225). – llonesmiz Aug 15 '16 at 11:43
  • @jv: Looks like you got the right answer - want to turn your comment into a proper answer? – MSalters Aug 15 '16 at 11:54
  • @jv_, I've already tried it, to no avail, looks like I'm missing something, will check it tomorrow. on the other hand I dont get it, what exactly stops all this macro stuff to handle correctly any number of parameters? – kreuzerkrieg Aug 15 '16 at 17:16
  • If one had to use this with too many parameters, how would one handroll what the macro is doing? – Carbon Nov 28 '17 at 16:02
1

This happens because BOOST_PP_TUPLE_TO_SEQ() is only implemented for 0 to 64 arguments (one of which is taken by the type in BOOST_FUSION_ADAPT_STRUCT()).

Ref: https://www.boost.org/doc/libs/1_67_0/boost/preprocessor/tuple/to_seq.hpp

As a workaround, you can put some of your struct members into their own struct, and use that struct type as a member in the outer struct. This lets you call BOOST_FUSION_ADAPT_STRUCT() twice: once for each inner struct type, and once for the outer. This easily gives you 63*63 = 3969 maximum fields.

John Zwinck
  • 239,568
  • 38
  • 324
  • 436
0

You can avoid this limitation of BOOST_PP_TUPLE_TO_SEQ() if you call the version without BOOST_PP_VARIADICS support

BOOST_FUSION_ADAPT_STRUCT(Data,
(auto,a01)(auto,a02)(auto,a03)(auto,a04)(auto,a05)(auto,a06)(auto,a07)(auto,a08)(auto,a09)(auto,a10)
(auto,a11)(auto,a12)(auto,a13)(auto,a14)(auto,a15)(auto,a16)(auto,a17)(auto,a18)(auto,a19)(auto,a20)
(auto,a21)(auto,a22)(auto,a23)(auto,a24)(auto,a25)(auto,a26)(auto,a27)(auto,a28)(auto,a29)(auto,a30)
(auto,a31)(auto,a32)(auto,a33)(auto,a34)(auto,a35)(auto,a36)(auto,a37)(auto,a38)(auto,a39)(auto,a40)
(auto,a41)(auto,a42)(auto,a43)(auto,a44)(auto,a45)(auto,a46)(auto,a47)(auto,a48)(auto,a49)(auto,a50)
(auto,a51)(auto,a52)(auto,a53)(auto,a54)(auto,a55)(auto,a56)(auto,a57)(auto,a58)(auto,a59)(auto,a60)
(auto,a61)(auto,a62)(auto,a63)(auto,a64)(auto,a65)(auto,a66)(auto,a67)(auto,a68)(auto,a69)(auto,a70))

I could not test it with MSVC but it works with gcc.

Max
  • 638
  • 1
  • 4
  • 19