You could use a trait that maps by descriptor. Let me show a contrived complex example that combines multiple pieces of meta data and even behavior:
Live On Coliru
#include <boost/describe.hpp>
#include <boost/mp11.hpp>
#include <iomanip>
#include <iostream>
namespace bd = boost::describe;
namespace mp11 = boost::mp11;
namespace MyLib {
struct Metadata {
bool some_flag = false;
std::string_view some_text = "";
static void some_action() { std::cout << "default action" << std::endl; }
};
template <typename D> constexpr inline Metadata meta_v{};
template <class T, class D1 = bd::describe_members<T, bd::mod_public | bd::mod_protected>,
class En = std::enable_if_t<!std::is_union<T>::value>>
void demo(T const&) {
mp11::mp_for_each<D1>([&](auto D) {
auto const& m = meta_v<decltype(D)>;
std::cout << "meta for " << D.name << ": { " << m.some_flag << ", "
<< quoted(m.some_text) << " }" << std::endl;
if (m.some_flag)
m.some_action();
});
}
} // namespace MyLib
// application
namespace MyLib {
struct Foo {
int bar;
std::string baz;
double qux;
};
BOOST_DESCRIBE_STRUCT(Foo, (), (bar, baz, qux))
// a shorthand, you might want to make this more generically elegant by deducing `Foo` instead
template <auto Mem>
using Desc = bd::descriptor_by_pointer<bd::describe_members<Foo, bd::mod_any_access>, Mem>;
// specialize some metadata
template <> constexpr inline Metadata meta_v<Desc<&Foo::baz>>{true, "hello"};
struct Special {
double some_flag = 42e-2;
std::string_view some_text = "specialized!";
static void some_action() { std::cerr << "stderr instead" << std::endl; }
};
template <> constexpr inline Special meta_v<Desc<&Foo::qux>>{};
} // namespace MyApp
int main() {
std::cout << std::boolalpha;
demo(MyLib::Foo{});
}
Prints
meta for bar: { false, "" }
meta for baz: { true, "hello" }
default action
meta for qux: { 0.42, "specialized!" }
stderr instead
Further Thoughts
You might also use a Fusion/Hana map to associate information to descriptors. It depends mostly on how you want your code to look of course.
UPDATE
Generalizing a bit (deducing the class type from a member pointer) and supporting member function pointers:
Live On Coliru
#include <boost/describe.hpp>
#include <boost/mp11.hpp>
#include <iomanip>
#include <iostream>
namespace bd = boost::describe;
namespace mp11 = boost::mp11;
namespace MyLib {
template <typename D> constexpr inline bool flag_v{};
template <
class T, class D1 = bd::describe_members<T, bd::mod_public | bd::mod_protected>,
class F1 = bd::describe_members<T, bd::mod_public | bd::mod_protected | bd::mod_function>,
class En = std::enable_if_t<!std::is_union<T>::value>>
void demo(T const&) {
mp11::mp_for_each<D1>([&](auto D) {
std::cout << "flag for " << D.name << ": " << flag_v<decltype(D)> << std::endl;
});
mp11::mp_for_each<F1>([&](auto D) {
std::cout << "flag for " << D.name << ": " << flag_v<decltype(D)> << std::endl;
});
}
namespace detail {
template <typename C, typename T> constexpr C deduce_class(T(C::*));
template <auto Mem> using Class = decltype(deduce_class(Mem));
template <auto Mem, typename /*Enable*/ = void> struct DescF;
template <auto Mem>
struct DescF<Mem, std::enable_if_t<std::is_member_function_pointer_v<decltype(Mem)>>> {
using type = bd::descriptor_by_pointer<
bd::describe_members<Class<Mem>, bd::mod_any_access | bd::mod_function>, Mem>;
};
template <auto Mem>
struct DescF<Mem, std::enable_if_t<not std::is_member_function_pointer_v<decltype(Mem)>>> {
using type =
bd::descriptor_by_pointer<bd::describe_members<Class<Mem>, bd::mod_any_access>,
Mem>;
};
}
template <auto Mem> using Desc = typename detail::DescF<Mem>::type;
} // namespace MyLib
// application
namespace MyApp {
struct Foo {
int bar;
std::string baz;
double qux;
};
struct Bar {
int quuz(double) { return 42; }
};
BOOST_DESCRIBE_STRUCT(Foo, (), (bar, baz, qux))
BOOST_DESCRIBE_STRUCT(Bar, (), (quuz))
} // namespace MyApp
using MyLib::Desc;
// specialize some metadata
template <> auto MyLib::flag_v<Desc<& MyApp::Foo::baz>> = true;
template <> auto MyLib::flag_v<Desc<& MyApp::Foo::qux>> = "surprise";
template <> auto MyLib::flag_v<Desc<& MyApp::Bar::quuz>> = "fun";
int main() {
std::cout << std::boolalpha;
MyLib::demo(MyApp::Foo{});
MyLib::demo(MyApp::Bar{});
}
Prints
flag for bar: false
flag for baz: true
flag for qux: surprise
flag for quuz: fun