Search code examples
c++c++17c++14operator-overloadingauto

Why does taking a function pointer to `operator new` compile in C++14, but not in C++17?


Consider the following code (godbolt link):

#include <cstdio>

int main() {
    auto foo = operator new;
    void* mem = foo(1);
    printf("%p", mem);
}

This code compiles on GCC, Clang, and MSVC with the C++ version set to C++ 14, but it fails to compile when using C++ 17 or later. On GCC, it fails with the following error:

error: unable to deduce 'auto' from 'operator new'

I expected the code to either compile or not compile in both versions. What changed in C++ 17 that makes it so that the type of operator new can no longer be deduced?


Solution

  • What changed in C++ 17 that makes it so that the type of operator new can no longer be deduced?

    This is P0035R41. It introduces in C++17 a new (pun intended) operator new to allow dynamic memory allocation for over-aligned data.

    You can find on cppreference.com the two following operators:

    void* operator new  ( std::size_t count );
    void* operator new  ( std::size_t count, std::align_val_t al );
    

    This makes auto foo = operator new ambiguous as it could match both operators.

    As user n. m. will see y'all on Reddit commented:

    operator new is not an addressable library function so this program has unspecified behaviour and is possibly ill-formed in any C++ standard.


    1)

    Problem statement

    To codify widespread existing practice, C++11 added the ability to specify increased alignment (a.k.a. over-alignment) for class types. Unfortunately (but also consistently with existing practice), C++11 did not specify any mechanism by which over-aligned data can be dynamically allocated correctly (i.e. respecting the alignment of the data). For example:

    class alignas(16) float4 {
      float f[4];
    };
    float4 *p = new float4[1000];
    

    In this example, not only is an implementation of C++ not required to allocate properly-aligned memory for the array, for practical purposes it is very nearly required to do the allocation incorrectly. In any event, it is certainly required to perform the allocation by a process that does not take the specified alignment value into account.

    This represents a hole in the support for alignment in the language, which really needs to be filled.