1202. integral_constant needs a spring clean

Section: 21.3.4 [meta.help] Status: NAD Submitter: Alisdair Meredith Opened: 2009-09-05 Last modified: 2016-01-28

Priority: Not Prioritized

View all other issues in [meta.help].

View all issues with NAD status.

Discussion:

The specification of integral_constant has been inherited essentially unchanged from TR1:

template <class T, T v>
struct integral_constant {
  static const T value = v;
  typedef T value_type;
  typedef integral_constant<T,v> type;
};

In light of 0x language changes there are several things we might consider changing, notably the form of specification for value.

The current form requires a static data member have storage allocated for it, where we could now implement without this using the new enum syntax:

template <class T, T v>
struct integral_constant {
  enum : T { value = v };
  typedef T value_type;
  typedef integral_constant type;
};

The effective difference between these two implementation is:

  1. No requirement to allocate storage for data member (which we hope but do not guarantee compilers strip today)
  2. You can no longer take the address of the constant as &integral_constant<T,v>::value;

Also note the editorial change to drop the explicit qualification of integral_constant in the typedef type. This makes it quite clear we mean the current instantiation, and cannot be mistaken for a recursive metaprogram.

Even if we don't mandate this implementation, it would be nice to give vendors freedom under QoI to choose their preferred representation.

The other side of this issue is if we choose to retain the static constant form. In that case we should go further and insist on constexpr, much like we did throughout numeric_limits:

template <class T, T v>
struct integral_constant {
  static constexpr T value = v;
  typedef T value_type;
  typedef integral_constant type;
};

[Footnote] It turns out constexpr is part of the Tentatively Ready resolution for 1019. I don't want to interfere with that issue, but would like a new issue to consider if the fixed-base enum implementation should be allowed.

[ 2009-09-05 Daniel adds: ]

I think that the suggested resolution is incomplete and may have some possible unwanted side-effects. To understand why, note that integral_constant is completely specified by code in 21.3.4 [meta.help]. While this is usually considered as a good thing, let me give a possible user-defined specialization that would break given the suggested changes:

enum NodeColor { Red, Black };

std::integral_constant<NodeColor, Red> red;

The reason why that breaks is due to the fact that current core language rules does only allow integral types as enum-bases, see 9.7.1 [dcl.enum]/2.

So, I think that we cannot leave the implementation the freedom to decide which way they would like to provide the implementation, because that is easily user-visible (I don't speak of addresses, but of instantiation errors), therefore if applied, this should be either specified or wording must be added that gives a note about this freedom of implementation.

Another possible disadvantage seems to me that user-expectations are easy to disappoint if they see a failure of the test

assert(typeid(std::integral_constant<int, 0>::value) == typeid(int));

or of

static_assert(std::is_same<decltype(std::integral_constant<int, 0>::value), const int>::value, "Bad library");

[ 2010-01-14 Moved to Tentatively NAD after 5 positive votes on c++std-lib. ]

Rationale:

We think that the suggested resolution is incomplete and may have some possible unwanted side-effects. (see Daniel's 2009-09-05 comment for details).

Proposed resolution: