We use extern "C" { ... }
to include C
header files in C++
. This does not seem to work if the C
file uses C99
keywords such as restrict
. For example:
test.h
#ifndef TEST_H
#define TEST_H
extern void test(int * restrict x, const int * restrict y);
#endif
test.c
#include "test.h"
int main(void)
{
int n = 1;
int m = 2;
test(&n, &m);
return 0;
}
test.cpp
extern "C" {
#include "test.h"
}
int main(void)
{
int n = 1;
int m = 2;
test(&n, &m);
return 0;
}
If we run gcc -Wall -Wextra -Wpedantic test.c -c
or clang -Weverything test.c -c
, the compilation is done silently without errors or warnings. However g++ test.cpp -c
results in a error. Similarly, clang++ test.cpp -c
fails.
Question:
Is there a portable way to use C99
(or higher) keywords in a header file, and then include that header file for use in C++
? Various C
libraries make use of the restrict
keyword, and it would seem desirable to want to be able to use them in a C++
library. As a simple example, the C
version of memcpy
(I know the C++
version of memcpy
does not use restrict
, of course, but this is a simple enough example):
https://en.cppreference.com/w/c/string/byte/memcpy
Please note: Non-portable solutions exists. Such as:
#if defined(__GNUC__) || defined(__clang__)
// GCC or clang
#define restrict __restrict__
#else
// MSVC
#define restrict __restrict
#endif
or something similar. I am seeking portable, standards-compliant solutions.
First, restrict
on a parameter has no effect in a function declaration that is not a definition. Qualifiers only apply to lvalues, and calls to a function pass arguments as plain values. Only in the function definition are the parameters objects that can have qualifiers. C 2024 6.7.7.4 says:
… In the determination of type compatibility and of a composite type,… each parameter declared with qualified type is taken as having the unqualified version of its declared type…
So, if you want to include a header (declarations only, no function definitions) in a C++ file, you can simply suppress the restrict
keyword, as with:
#if __cplusplus
#define restrict
#endif
(restrict
could have an effect in a function declaration if it is inside a parameter rather than directly on the parameter, as in void foo(int * restrict *p);
. I do not believe I have ever seen that used in code. If it were present in that way, it would make the C++ altered function declaration incompatible with the C definition.)
Second, even in a function definition, the only purpose of restrict
is to promote optimization. Removing restrict
from a correct program keeps a correct program, with the _Generic
exception noted below. C 2024 6.7.4.1 says:
… The intended use of the
restrict
qualifier (like theregister
storage class) is to promote optimization, and deleting all instances of the qualifier from all preprocessing translation units composing a conforming program does not change its meaning (i.e. observable behavior), unless_Generic
is used to distinguish whether or not a type has that qualifier…
I have cited C 2024, but this is the same from C 1999 on, except there was no _Generic
in C 1999.