Bug 68891 - must use a typedef to declare a conversion to 'double (&)[3]'
Summary: must use a typedef to declare a conversion to 'double (&)[3]'
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 12.1.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: accepts-invalid
Depends on:
Blocks:
 
Reported: 2015-12-14 10:02 UTC by Mathieu Malaterre
Modified: 2024-01-08 16:23 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2021-11-04 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Mathieu Malaterre 2015-12-14 10:02:56 UTC
Per my understanding of C++ standard section ยง12.3.2, the following piece of code should not compile:

$ cat c.cxx
#include <iostream>
struct V
{
  (&operator double ())[3] {
    return v;
  }
  double v[3];
};

static void Print( const double (&a)[3] )
{
  std::cout << a[0] << "," << a[1] << "," << a[2] << std::endl;
}

int main()
{
  V v = {0,1,2};
  Print( v );
  return 0;
}

Seems to be valid c++ for gcc 5.2.1:

$ g++ -Wall -W -pedantic c.cxx && ./a.out 
0,1,2

The only accepted syntax should be using a `typedef` keyword:

  typedef double (&array_ref)[3];
  operator array_ref () { return v; }
Comment 1 Mathieu Malaterre 2021-11-04 08:24:26 UTC
Here is the output from clang++:

 error: cannot specify any part of a return type in the declaration of a conversion function; use a typedef to declare a conversion to 'double (&)[3]'

% clang++ --version
Debian clang version 11.0.1-2
Comment 2 Jonathan Wakely 2021-11-04 09:44:46 UTC
Reduced:

struct V
{
  (&operator double ())[3] {
    return v;
  }
  double v[3];
};

static void Print( const double (&)[3] )
{
}

int main()
{
  V v = {0,1,2};
  Print( v );
}

EDG accepts it too. MSVC says:

error C2586: incorrect user-defined conversion syntax: illegal indirections
Comment 3 Mital Ashok 2024-01-08 16:23:46 UTC
This is also erroneously named with `operator double`:

assert(V{0,1,2}.operator double()[1] == 1.0);
using T = double;
assert(V{0,1,2}.operator T()[1] == 1.0);
using U = double(&)[3];
// 'struct V' has no member named 'operator U'
// V{0,1,2}.operator U();

And a similar thing happens with user defined conversions to function pointers / references