https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87663

--- Comment #7 from Lukas Mosimann <lumosimann at gmail dot com> ---
Thanks! I will do that.

First lets sum up state here such that it's not required to read through all
comments. I am playing around with integral constant and an "exponential
wrapper". First the "exponential wrapper":

```
template <int X, int A>
struct F : integral_constant<int, F<X + (1 << A), A - 1>::value -
                                      F<X, A - 1>::value> {};

template <int X>
struct F<X, 0> : integral_constant<int, X> {};

int main() {
    F<0, 14>::value;
    return 0;
}
```
I.e., we simply instantiate a huge set of integral constants. Now I play with
different integral_constants a measure compilation time.

=== V1 0.8s ===
template <typename T, T v>
struct integral_constant {
    static constexpr T value = v;
};


=== V2 4.4s === (used by type_traits)
template <typename T, T v>
struct integral_constant {
    static constexpr T value = v;
    using value_type = T;
};

=== V3 4.2s ===
template <typename T, T v>
struct integral_constant {
    using value_type = T;
    static constexpr T value = v;
};

=== V4 23 s === (!!)
template <typename T, T v>
struct integral_constant {
    using value_type = T;
    static constexpr value_type value = v;
};

Currently I am working with a modified version of V2 (4.4s):

template <typename T, T v>
struct integral_constant {
    static constexpr T value = v;
    using value_type = int;
};

In this case I see that we always create a new type variant of int (I guess one
per integral constant) through set_underlying type, and at another point we
iterate through large parts of the list to get the correct variant again (over
build_qualified_type). More precisely:
1) We first do build_qualified_type for value. This iterates through the whole
list and at some point finds "plain const int" (no typedef) - no new type
variant required.
2) We create a new type variant of int referring to the alias in this specific
integral_constant. This is prepended to the list of type variants, i.e., in the
next 1) we need to iterate over one additional entry than before to find "plain
const int".
Therefore, integral constant instantiation gets more expensive with each
instance.

I have seen the comment above set_underlying type, but my question is more
whether this is always needed (it is only talking about debugging and protoize
- so is it also required in a build without debugging information?).
And yes, it might also be possible to do it more efficient: Do all variants
need to be stored in this list? Is this the natural order for a list - and is a
list the right data structure for this?

I will post to the mailing list pointing to this comment.

Reply via email to