Reputation: 1851
I'm trying to implement a trait-based policy subsystem and I have an issue which I don't really know how to tackle (if it's even possible). I have a traits that looks like this:
template <typename ValueT, typename TagT = void, typename EnableT = void>
struct TPolicyTraits
{
static void Apply(ValueT& value) { }
};
And this trait can be specialized as such:
struct MyPolicy {};
template <typename ValueT>
struct TPolicyTraits<ValueT, MyPolicy>
{
static void Apply(ValueT& value) { /* Implementation */ }
};
I would like to register policy at compile time in a sort of linked list. The policy system would be used like this:
namespace PolicyTraits
{
template <typename ValueT, typename TagT>
using TPolicyTraitsOf = TPolicyTraits<std::decay_t<ValueT>, TagT>;
template <typename ValueT>
void Apply(ValueT&& value)
{
// todo iterate through constexpr tag list and apply policies
}
template <typename TagT>
constexpr void Enable()
{
// todo add tag to constexpr list
}
}
int main()
{
PolicyTraits::Enable<MyPolicy>();
PolicyTraits::Apply(std::string());
}
Is there any way to achieve this?
Upvotes: 1
Views: 194
Reputation: 275800
Compile time metaprogramming is for the most part pure. This means each expression's result is determined by its arguments.
There are exceptions that can get around it by using argument dependent lookup and friend functions and SFINAE in quite frankly insane ways.
Don't do that.
Build the policy traits class from its policies, don't hack around to get global state.
TL;DR technically possible, but a horrible idea. Don't do it.
Possibly an adjacent problem to the one you drescribe has a clean and elegant solution.
Upvotes: 5
Reputation: 56068
No.
constexpr
things may not allocate memory with new
. This limitation may eventually be removed. But for now, that's how it is.
This precludes the use of any dynamically sized data type.
OTOH, constexpr
allows you to create statically sized data types with computed sizes (provided that computation can be done at compile time) relatively easily. This can probably be leveraged to do something like what you want.
Except that building a type like this across several different compilation units is again not something that can be done. And that limitation is intrinsic to the C++ compile/link chain and will not be able to be removed without significantly changing it.
So, No.
Upvotes: 1