I am using the following smart enum structure:
/* MySmartEnum.hpp */
#pragma once
#include <array>
template <class E>
static const auto& value_string_pairs();
#define MY_EXPAND(x) x
#define MY_ARRAY_PAIR(name, x) { #x, name::x }
#define MY_STR_CONCAT_(a, ...) a##__VA_ARGS__
#define MY_STR_CONCAT(a, ...) MY_STR_CONCAT_(a, __VA_ARGS__)
#define MY_ARG_COUNT_(_1,_2,_3,_4,VAL,...) VAL
#define MY_ARG_COUNT(...) MY_EXPAND(MY_ARG_COUNT_(__VA_ARGS__,4,3,2,1))
#define MY_LOOP_1(f, n, x)      f(n,x)
#define MY_LOOP_2(f, n, x, ...) f(n,x) , MY_EXPAND(MY_LOOP_1(f, n, __VA_ARGS__))
#define MY_LOOP_3(f, n, x, ...) f(n,x) , MY_EXPAND(MY_LOOP_2(f, n, __VA_ARGS__))
#define MY_ENUM_IMPL(name, loop_func_name, ...)                                             \
    template<> inline const auto& value_string_pairs<name>() {                              \
        using element_t = std::pair<const char*, name>;                                     \
        static const std::array<element_t, MY_ARG_COUNT(__VA_ARGS__)> values = { element_t  \
            MY_EXPAND(loop_func_name(MY_ARRAY_PAIR, name, __VA_ARGS__)) };                  \
        return values; }
#define MY_ENUM_CLASS(name, ...) enum class name { __VA_ARGS__ }; \
    MY_ENUM_IMPL(name, MY_STR_CONCAT(MY_LOOP_, MY_ARG_COUNT(__VA_ARGS__)), __VA_ARGS__)
Then I maintain an additional file with all the enum types:
/* Enums.hpp */
#pragma once
#include "MySmartEnum.hpp"
MY_ENUM_CLASS(Timespan, Week, Month, Year)
MY_ENUM_CLASS(Interpolation, Linear, Cubic)
For example MY_ENUM_CLASS(Timespan, Week, Month, Year) expands to
enum class Timespan { Week, Month, Year };
template<>
inline const auto& value_string_pairs<Timespan>() {
    using element_t = std::pair<const char*, Timespan>;
    static const std::array<element_t, 3> values = { element_t
        { "Week",  Timespan::Week  },
        { "Month", Timespan::Month },
        { "Year",  Timespan::Year  } };
    return values;
}
So right now, everything is implemented in the header. But I want to move the implementation to an Enums.cpp file. Firstly, I can easily change MY_ENUM_CLASS(...) to only define the enum & function signature in Enums.hpp:
#define MY_ENUM_CLASS(name, ...) enum class name { __VA_ARGS__ };  \
    template<> const auto& value_string_pairs<name>();
But how do I move the implementation of value_string_pairs<Timespan>() into Enums.cpp, but without having to list all enum values again? Is there a way to #include "Enums.hpp" in Enums.cpp, un-define MY_ENUM_CLASS and then re-define MY_ENUM_CLASS inclusive of MY_ENUM_IMPL such that MY_ENUM_CLASS(Timespan, Week, Month, Year) expands to the full function implementation (but only in Enums.cpp)?
