mardi 25 mai 2021

Calculate limit of a range at compile time

Given you ONLY have as a tool a SFINAE class, that accepts an index and yields std::true_type if it is in range, how could one find the limit? This are the exact requiremants, NOTHING else can be used.

This is an example signature for a struct. L here is for testing. In the real struct there will be typename T as a second parameter, but it is irrelevant to the problem.

template <size_t I, size_t L = 6000>
struct is_in_range : std::integral_constant<bool, (I < L)> {};

For example: you have a range of 6000 elements. is_in_range<2>() will be true, is_in_range<6001>() will be false. I need to find the limit, which is in this case 6000.

I know that you could basically refer to the binary search, but the thing is, it has to be as optimal as possible and generate as little instantiations as possible.

For the template part I see 2 ways:

  • template constexpr recursive function (a bad one, bloated code, but I can do that)
  • SFINAE (too complex for me)

In order not to pollute the comments, here is a clarification.
YES, it is kind of an XY problem. But the real problem is TOO COMPLEX to describe. And since SO rules encourage to separate questions, this is the result. I have a problem which might be solved in 2 ways, and the first one can't be used. So, hence the question. Please, refer to the question, not to the reason I am asking.


So, here is an explanation of an actual problem.

In order to deduce at compile time a member of a structure I use aggregate initialization.

template <typename Allowed>
struct explicitly_convertible
{
   operator Allowed();
}

struct pod
{
   int a;
   int arr[46];
   char c;
   float arr2[38];
};

Implementation does the following:

// checks if this is well-formed to deduce the type of an element
   decltype(pod);

So, as you see, the only way to deduce an array size, is to probe the initialization of T with N elements while aggregate initializating.

In C++ a function or a method can't return an array, so this is not acceptable:

template <typename T, size_t N>
struct non_acceptable
{
   operator T[N]();
}

Aucun commentaire:

Enregistrer un commentaire