c++macrosprecompiler

Is there a way to merge / concatenate precompiler lists with C++ macros?


I have two lists:

#define LIST1 {1, 2, 3}
#define LIST2 {4, 5, 6}

and using C++ macros I would like to write something like this:

// Obviously doesn't work
#define MERGE LIST1 ## LIST2
int my_array[] = MERGE;

to yield:

int my_array[] = {1, 2, 3, 4, 5, 6};

during compile-time.

Is something like this possible? There are other questions concerning this with strings, however I can't figure out for the life of me how to do this with non-string array declarations.

Edit: I certainly would prefer to not use macros, and would prefer that the list format be different as well. Unfortunately, the header file that contains these list definitions isn’t a file that I can edit.


Solution

  • Don't use macros unless there is no other option, prefer templates. They are typesafe.

    For example you can make a compile time evaluated function (constexpr) that merges two lists (arrays) and returns an array.

    #include <array>
    
    // type_t is the type held by the array (an int in this example)
    // N = size of first array
    // M = size of second array
    // const type_t(&arr)[N] is the syntax for passing an array by const reference
    
    template<typename type_t, std::size_t N, std::size_t M>
    constexpr auto merge(const type_t(&arr1)[N], const type_t(&arr2)[M])
    {
        std::array<type_t, N + M> arr{}; // this initialization is needed in constexpr
        std::size_t index{ 0 };
    
        for (const auto& value : arr1) arr[index++] = value;
        for (const auto& value : arr2) arr[index++] = value;
    
        return arr;
    }
    
    int main()
    {
        constexpr auto arr = merge({ 1,2,3 }, { 4,5,6 });
        constexpr auto strings = merge( {"abc", "def" }, {"ijk", "lmn"} );
    
        // static_assert is like assert, but evaluated at compile time.
        static_assert(arr.size() == 6);
        static_assert(arr[4] == 5);
    
        return 0;
    }