I am getting an error when compiling the following code after upgrading from C++17 to C++20 with msvc:
#include <tuple>
template <typename T>
void alloc(void* dest)
{
using ty = decltype(new T);
reinterpret_cast<ty&>(dest) = new T;
}
int main()
{
int obj[5][10];
alloc<decltype(obj)>(obj);
return 0;
}
The error is:
<source>(7): error C2668: 'operator new[]': ambiguous call to overloaded function
predefined C++ types (compiler internal)(58): note: could be 'void *operator new[](size_t)'
predefined C++ types (compiler internal)(33): note: or 'void *operator new(size_t)'
<source>(7): note: while trying to match the argument list '(unsigned __int64)'
<source>(13): note: see reference to function template instantiation 'void alloc<int[5][10]>(void *)' being compiled
(This is a minimal repro, when I remove the tuple include then it compiles however I can't just remove the include in the real code).
Using C++ insights I can see that the c++ 17 was doing what I expected, the template substitution generated new int[5UL][10];
for new T
.
I'm not sure why this is now ambiguous in C++ 20, and how I can specify what version of new I need.
This looks like a compiler bug.
In your instantiation of new T
the allocated type is T
and is an array type. Consequently only operator new[]
should be looked up for the new-expression's allocation function. This has been the case since the first C++ standard and is still the case. So void *operator new(size_t)
shouldn't even be a candidate to consider in the supposedly-ambiguous overload resolution.
However the code does have undefined behavior, see my comment under the question.