Make copyObject work in C++
Calling copyObject fails in C++ with an error like in most setups:
error: use of undeclared identifier 'typeof'; did you mean 'typeid'
This is due to the C compiler supporting used to compile postgres
supporting typeof, but that function actually not being present in the
C++ compiler. This fixes that by using decltype instead of typeof when
including the header in C++.
Realized because of Thomas' not about how much of our headers should
work in C++, and remembering I hit this specific problem myself.
Another approach would be to force the value of HAVE_TYPEOF to 0 if __cplusplus.
Attachments:
Jelte Fennema-Nio <postgres@jeltef.nl> writes:
Calling copyObject fails in C++ with an error like in most setups:
error: use of undeclared identifier 'typeof'; did you mean 'typeid'
This is due to the C compiler supporting used to compile postgres
supporting typeof, but that function actually not being present in the
C++ compiler. This fixes that by using decltype instead of typeof when
including the header in C++.
Hmm, this only fixes the one use-case. Admittedly we have only one
use-case, but as soon as we have another we'll have a new problem.
How about instead modifying the macro? Maybe something like this
in c.h (untested):
#ifdef __cplusplus
#undef typeof
#define typeof decltype
#define HAVE_TYPEOF 1
#endif
Another approach would be to force the value of HAVE_TYPEOF to 0 if __cplusplus.
That would be sad, because we'd lose the type checking ability
of copyObject() in C++ code.
BTW, grepping finds a number of random references to __typeof__ and
__typeof, which probably ought to be updated to be just typeof.
regards, tom lane
On 05.12.25 15:46, Jelte Fennema-Nio wrote:
Calling copyObject fails in C++ with an error like in most setups:
error: use of undeclared identifier 'typeof'; did you mean 'typeid'
This is due to the C compiler supporting used to compile postgres
supporting typeof, but that function actually not being present in the
C++ compiler. This fixes that by using decltype instead of typeof when
including the header in C++.Realized because of Thomas' not about how much of our headers should
work in C++, and remembering I hit this specific problem myself.Another approach would be to force the value of HAVE_TYPEOF to 0 if __cplusplus.
In the long run, I would like to change copyObject() to use
typeof_unqual instead, because that handles qualifiers more correctly.
(Currently, copyObject() of a const-qualified pointer results in a
const-qualified pointer, which is nonsensical because the reason you
made the copy is that you can modify it.) See attached patch for an
example. Does C++ have something that is semantically similar to that?
Attachments:
On 07.12.25 20:45, Tom Lane wrote:
Hmm, this only fixes the one use-case. Admittedly we have only one
use-case, but as soon as we have another we'll have a new problem.
How about instead modifying the macro? Maybe something like this
in c.h (untested):#ifdef __cplusplus
#undef typeof
#define typeof decltype
#define HAVE_TYPEOF 1
#endif
AFAICT, both gcc and clang support typeof in C++ mode as well. So this
kind of renaming could be confusing.
On Sun Dec 7, 2025 at 8:45 PM CET, Tom Lane wrote:
#ifdef __cplusplus
#undef typeof
#define typeof decltype
#define HAVE_TYPEOF 1
#endif
Went with defining pg_exprtype (pg_typeof already exists). Undefining
typeof seemed a bit heavy-handed. Especially since I think it would be
nice to backport this so C++ extensions can use copyObject directly.
BTW, grepping finds a number of random references to __typeof__ and
__typeof, which probably ought to be updated to be just typeof.
Added a follow on patch that starts using pg_exrtype in all those
places.
Attachments:
On 08.12.2025 08:57, Peter Eisentraut wrote:
On 05.12.25 15:46, Jelte Fennema-Nio wrote:
Calling copyObject fails in C++ with an error like in most setups:
error: use of undeclared identifier 'typeof'; did you mean 'typeid'
This is due to the C compiler supporting used to compile postgres
supporting typeof, but that function actually not being present in the
C++ compiler. This fixes that by using decltype instead of typeof when
including the header in C++.Realized because of Thomas' not about how much of our headers should
work in C++, and remembering I hit this specific problem myself.Another approach would be to force the value of HAVE_TYPEOF to 0 if
__cplusplus.In the long run, I would like to change copyObject() to use
typeof_unqual instead, because that handles qualifiers more correctly.
(Currently, copyObject() of a const-qualified pointer results in a
const-qualified pointer, which is nonsensical because the reason you
made the copy is that you can modify it.) See attached patch for an
example. Does C++ have something that is semantically similar to that?
Since C++11 there's std::remove_const which can be used as
std::remove_const<decltype(type)>::type.
I'm not aware of anything pre C++11, except for rolling your own variant
of std::remove_const via template specialization.
--
David Geier
On Mon, 8 Dec 2025 at 09:33, David Geier <geidav.pg@gmail.com> wrote:
Since C++11 there's std::remove_const which can be used as
std::remove_const<decltype(type)>::type.I'm not aware of anything pre C++11, except for rolling your own variant
of std::remove_const via template specialization.
I think depending on C++11 sounds fine, since we're also depending on
C11 and people tend to use much more recent C++ versions than C
versions (so probably we could even require something higher).
Peter Eisentraut <peter@eisentraut.org> writes:
AFAICT, both gcc and clang support typeof in C++ mode as well. So this
kind of renaming could be confusing.
Hm, if that's true then we should not have to do anything ...
so why is Jelte reporting a problem?
regards, tom lane
On Mon, 8 Dec 2025 at 15:51, Tom Lane <tgl@sss.pgh.pa.us> wrote:
Peter Eisentraut <peter@eisentraut.org> writes:
AFAICT, both gcc and clang support typeof in C++ mode as well. So this
kind of renaming could be confusing.Hm, if that's true then we should not have to do anything ...
so why is Jelte reporting a problem?
Seems it's related to -std=c++17 vs -std=gnu++17. I was compiling my
code with the former, which throws the error in question[1]https://godbolt.org/z/fz567hs1r. Compiling
with the latter works fine[2]https://godbolt.org/z/cq1se55bn.
So I guess it depends what we want to require from C++ extensions.
Should we require them to compile with gnu extensions? My opinion on
that would be no.
[1]: https://godbolt.org/z/fz567hs1r
[2]: https://godbolt.org/z/cq1se55bn
On Mon, 8 Dec 2025 at 08:57, Peter Eisentraut <peter@eisentraut.org> wrote:
In the long run, I would like to change copyObject() to use
typeof_unqual instead, because that handles qualifiers more correctly.
(Currently, copyObject() of a const-qualified pointer results in a
const-qualified pointer, which is nonsensical because the reason you
made the copy is that you can modify it.) See attached patch for an
example. Does C++ have something that is semantically similar to that?
Yes, there's a std::remove_cv, std::remove_const, and std::remove_volatile[1]https://en.cppreference.com/w/cpp/types/remove_cv.html.