C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Expand arrays with known sizes using ellipses

From: Chris Gary <cgary512_at_[hidden]>
Date: Fri, 22 Sep 2023 12:50:35 -0600
Other rough ideas I've had since c++11:

`template< typename ...ValuesT >
struct Mirror
{
  // First-class tuples.
ValuesT ...values;

  Mirror( cosnt ValuesT &..values )
  : values{ values }... // <- Note '...' _after_ the IL
  {}
};

struct MiscData
{
  unsigned passes;
  float gamma;
  int example;
  double value;
};

void DoThings( unsigned a, float b, int c, double d );

void Fn()
{
  MiscData data = GetFromElsewhere();

  // Unpack public type members of MiscData in declaration order.
  // Unpack public value members of a MiscData instance in the same order.
  Mirror< MiscData... > clone{ data... };

  // Use some kind of indexing mechanism.
  // I've opted for "<index>", since it seems unambiguous next to a value
member.
  auto &gammaClone = clone.values<0>;

  // With CTAD (this is already valid):
  Mirror clone2{ data... };

  // Same thing as with "data", just unpack public members in declaration
order.
  DoThings( clone2... );
}

template< typename Arg_t >
Arg_t Flatten( Arg_t arg )
{ return arg; }

// Should produce a single-level Mirror<>
template< typename Arg_t, typename ...Args_t >
auto Flatten( Arg_t arg, Args_t ...args )
{
  return Mirror{ arg, Flatten( args )... };
}`

I imagine there could be some places where this is ambiguous.

I think the thread ought to be re-started as "Unpack anything with ..." or
"Nested ellipses".

On Thu, Sep 21, 2023 at 2:21 PM Chris Gary <cgary512_at_[hidden]> wrote:

> Maybe that information can be hoisted into the function's metadata,
>> inducing a set of functions based on their parameters?
>>
>> Admittedly, the binding criteria are complicated.
>>
>> More concretely (somewhat),
>>
>> read this:
>> `constexpr auto q = 123456.789_qq;`
>>
>> like this:
>> `constexpr auto q = operator ""_qq( "123456.789", 10u );`
>>
>> or, closer to what I mean:
>>
>> `constexpr auto q = operator ""_qq( "123456.789" );`
>>
>> where the definition is:
>>
>> `template< std::size_t size_ >
>> constexpr mp_rational operator ""_qq( const char (&lit)[size_] )
>> requires( std::is_constant_evaluated() ? matches_std_numeric_literal( lit
>> ) : true )
>> {
>> if( std::is_constant_evaluated() )
>> {
>> using MQQ = materialize_qq_from_static_literal< lit... >;
>> }
>> else
>> {
>> if( ! matches_std_numeric_literal( lit ) )
>> {
>> throw std::invalid_argument{};
>> }
>>
>> // etc...
>> }
>> }`
>>
>> loosely speaking.
>>
>> Template instantiations and static function invocations given known
>> parameters can be viewed uniformly as unique "types". This is already
>> known, since constexpr functions can be used to instantiate templates (e.g.
>> a non-type parameter is identified by its constructor arguments).
>>
>> So, an alternative assuming something like constexpr static would work
>> intuitively:
>>
>> `template< typename CodeUnitT, std::size_t size_ >
>> constexpr mp_rational operator ""_qq( const CodeUnitT (&lit)[size_] )
>> requires( std::is_constant_evaluated() ? matches_std_numeric_literal( lit
>> ) : true )
>> {
>> // At compile-time: The requires clause is evaluated, raising errors
>> wherever
>> // the data can be examined directly.
>> //
>> // At runtime: Throws an exception if lit violates whats in the
>> requires() clause above.
>> return materialize_qq_from_static_literal_as_fn( lit ).bind();
>> }`
>>
>> Reflecting on this, what I'm really after is just materializing ordinary
>> data from compile time into static data...
>>
>> To my original point, being able to expand arrays into other arrays (or
>> function parameter lists) seems obvious to me.
>>
>

Received on 2023-09-22 18:50:48