I am writing a library where object parameters that are inherently static are built into the type using non-type template parameters. Doing this offers massive performance optimization over an implementation where these values are runtime values (small benchmarks measured at 10x, expected 5-7x). However, I find that C++ does not support this idiom very well. I am trying to refactor the library to make it easier to use by developers that aren't very familiar with templates or metaprogramming.
I would like to offer constexpr functions that simplify the extraction of static constexpr member variables (that are used to propogate the static values through the types), so that users do some basic metaprogramming without understanding the heavy machinery behind the scenes. For example,
#include <type_traits>
template <int A, int B>
class Example {
public:
static constexpr auto C = A + B;
private:
int b {0};
};
template <int A, int B>
constexpr auto getC(Example<A, B> e) { return decltype(e)::C; }
/**** USER CODE ****/
int main()
{
Example<1, 2> e;
Example<2, getC(e)> f;
}
This does not work, e being non-constexpr can be used in a constexpr context, even if you aren't using the value (strangely if Example had no runtime members, it would work). One could write decltype(e)::C instead, but if it's a reference they would have to std::remove_reference<decltype(C)>::type::C and of course they would have to know to do this, and know enough to get around common problems like the remove_reference call. And at that point we are off in the weeds for the typical programmer this library is meant for.
constexpr functions don't work, macros don't work with the type system so they are also insufficient, how else could I accomplish this?