I am developing a C++17 framework that has optional third-party dependencies and I'd like to construct an std::array that contains the names of the available dependencies.
The CMake file sets preprocessor definitions such as HAS_DEPENDENCY1, HAS_DEPENDENCY2, ..., so writing such a function with an std::vector is quite easy:
using literal = const char*;
std::vector<literal> available_dependencies() {
std::vector<literal> dependencies{};
#ifdef HAS_DEPENDENCY1
dependencies.emplace_back("dependency 1");
#endif
#ifdef HAS_DEPENDENCY2
dependencies.emplace_back("dependency 2");
#endif
return dependencies;
}
I'd like to have a compile-time, constexpr equivalent of that. I tried this:
constexpr static std::array available_dependencies{
#ifdef HAS_DEPENDENCY1
"dependency 1",
#endif
#ifdef HAS_DEPENDENCY2
"dependency 2"
#endif
};
but there are two issues:
- if no dependency is available (which can happen), the compiler cannot deduce the template arguments of
std::array(the array is empty). - if dependency 1 is available but dependency 2 isn't, the code doesn't compile because of the trailing comma.
I managed to address the first issue with something like:
template <typename... Literals>
constexpr std::array<literal, sizeof...(Literals)> make_literal_array(Literals&&... literals) {
return {literals...};
}
but this doesn't support trailing commas. I tried with an std::initializer_list (they allow trailing commas), but couldn't get it to work.
Perhaps you'll be more inspired than me?