3
votes

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

3
and what's the error?phuclv
@m.s. Great idea, definitely it will helpkreuzerkrieg
@LưuVĩnhPhúc added to the questionkreuzerkrieg

3 Answers

2
votes

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++.

1
votes

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.

0
votes

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.