Issue
For this struct and function:
typedef struct data_s
{
int i1;
int i2;
} data_t;
void print_data_passed_by_ptr(const data_t *data)
{
printf(" i1 = %i\n"
" i2 = %i\n\n",
data->i1,
data->i2);
}
the following works fine in C. As you can see below, I'm creating a data_t
struct in-place and passing the address of it, as an R-value (meaning that it is not assigned to a variable), to the print_data_passed_by_ptr()
function:
// Print R-value struct passed by ptr
print_data_passed_by_ptr(&(data_t){
.i1 = 7,
.i2 = 8,
});
My C build command is:
gcc -Wall -Wextra -Werror -O3 -std=c17 \
struct_pass_R_values_by_cpp_reference_and_ptr.c -o bin/a && bin/a
But, in C++ it fails with
error: taking address of temporary [-fpermissive]
My C++ build command is:
g++ -Wall -Wextra -Werror -O3 -std=c++17 \
struct_pass_R_values_by_cpp_reference_and_ptr.c -o bin/a && bin/a
So, I added -fpermissive
to my C++ build command:
g++ -Wall -Wextra -Werror -O3 -std=c++17 -fpermissive \
struct_pass_R_values_by_cpp_reference_and_ptr.c -o bin/a && bin/a
and now the C++ build fails with this:
error: taking address of temporary [-Werror=permissive]
I tried turning off -Werror=permissive
with -Wno-error=permissive
(see here for that GCC documentation: https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html, and search the page for -Wno-error=
), but that's not a valid option. New build cmd I attempted:
g++ -Wall -Wextra -Werror -O3 -std=c++17 -fpermissive -Wno-error=permissive \
struct_pass_R_values_by_cpp_reference_and_ptr.c -o bin/a && bin/a
...fails with:
cc1plus: error: -Werror=permissive: no option -Wpermissive
So, how do I solve this to force this C code to build in C++? Either suppressing the warning/error, OR providing some modification to the code other than the one shown just below are acceptable answers. I want the code to compile as C also, not just C++, in the end.
I know I can use "const reference" in C++ instead of ptr, like this, and that's great and all and it might answer somebody else's question, but that's not my question:
void print_data_passed_by_cpp_reference(const data_t& data)
{
printf(" i1 = %i\n"
" i2 = %i\n\n",
data.i1,
data.i2);
}
// Print R-value struct passed by C++ reference
print_data_passed_by_cpp_reference({
.i1 = 9,
.i2 = 10,
});
I also know I can remove -Werror
and keep -fpermissive
to make it build, with warnings, like this:
eRCaGuy_hello_world/cpp$ g++ -Wall -Wextra -O3 -std=c++17 -fpermissive \
struct_pass_R_values_by_cpp_reference_and_ptr.c -o bin/a && bin/a
struct_pass_R_values_by_cpp_reference_and_ptr.c: In function ‘int main()’:
struct_pass_R_values_by_cpp_reference_and_ptr.c:87:5: warning: taking address of temporary [-fpermissive]
});
^
Hello world.
i1 = 7
i2 = 8
i1 = 9
i2 = 10
...but I'd really like to keep -Werror
on and make that warning go away.
Solution
How to automatically pass an R-value parameter into a function as a const ptr for C and as a const reference for C++
(emphasis added to my original quote)
So, how do I solve this to force this C code to build in C++? Either suppressing the warning/error, OR providing some modification to the code other than the one shown just below are acceptable answers. I want the code to compile as C also, not just C++, in the end.
This works! It is one approach. If there are ways to disable the warning/error in gcc via command-line options I'd still like to know those though.
This is pretty clever I think. It passes the R-value by const ptr for C and by const reference for C++ by using two separate definitions for the print_data()
function and the DATA_T
macro, depending on the language.
#ifndef __cplusplus
// For C
void print_data(const data_t *data)
{
printf(" i1 = %i\n"
" i2 = %i\n\n",
data->i1,
data->i2);
}
#else
// For C++
void print_data(const data_t& data)
{
printf(" i1 = %i\n"
" i2 = %i\n\n",
data.i1,
data.i2);
}
#endif
#ifndef __cplusplus
// For C
#define DATA_T &(data_t)
#else
// For C++
#define DATA_T // leave empty
#endif
Usage:
// Print R-value struct passed by C++ reference, OR by C ptr, depending on
// whether this code is compiled as C or C++
print_data(DATA_T{
.i1 = 9,
.i2 = 10,
});
Build commands:
# For C
gcc -Wall -Wextra -Werror -O3 -std=c17 \
struct_pass_R_values_by_cpp_reference_and_ptr.c -o bin/a && bin/a
# For C++
g++ -Wall -Wextra -Werror -O3 -std=c++17 \
struct_pass_R_values_by_cpp_reference_and_ptr.c -o bin/a && bin/a
See my experimental test code above inside struct_pass_R_values_by_cpp_reference_and_ptr.c
in my eRCaGuy_hello_world repo.
Answered By - Gabriel Staples Answer Checked By - Dawn Plyler (WPSolving Volunteer)