C++ reserved word as function pointer name in C struct
Asked Answered
J

1

5

I suspect I know the answer to this already, but am curious if any experts out there have any tricks.

I have a C library built with the intention of being a C framework (unsafe functions unused, similar naming convention cross-platform, etc.). This works fine, up until I try to use it within a C++ project, where the C 'namespaced' function name conflicts with a C++ reserved word, in this case delete.

Here's the 'file' namespace, where I want it delete to be one of the function names:

#include <stdio.h>

#if defined(__linux__) || defined(BSD)
#   include <fcntl.h>
#endif


#if defined(__cplusplus)
#   if defined(_MSC_VER)
#       pragma warning ( push )
        // Disable: default constructor could not be generated
#       pragma warning ( disable : 4510 )
        // Disable: assignment operator could not be generated
#       pragma warning ( disable : 4512 )
        // Disable: struct <unnamed-tag> can never be instantiated
#       pragma warning ( disable : 4610 )
#   endif
extern "C" {
#endif



typedef struct
{
    int(*const close)(FILE* fp);
    int(*const copy)(const char* src, const char* dest);
    int(*const delete)(const char* path);
    int(*const flush)(FILE* fp);
    long(*const get_file_size)(FILE* fp);
    long(*const get_size)(const char* path);
    FILE*(*const open)(const char* name, const char* modes);
    int(*const path_exists)(const char* path);
    size_t(*const read)(void* ptr, size_t size, size_t count, FILE* stream);
    size_t(*const write)(const void* ptr, size_t size, size_t count, FILE* stream);

} namespace_file;

extern namespace_file const file;



#if defined(__cplusplus)
}   // extern "C"
#   if defined(_MSC_VER)
#       pragma warning ( pop )
#   endif
#endif

Now I'm writing some tests using gtest, and encounter the reserved word issue - is there anyway to bypass this, or shall I simply rename the function to purge or similar?

TEST(cfwkFile, fDelete)
{
    // all three of these error as 'delete' is reserved
    EXPECT_EQ(0, file.delete(CFWK_TEST_FAIL_FILE));
    EXPECT_EQ(1, file.delete(CFWK_TEST_PASS_FILE));
    EXPECT_EQ(1, file.delete(CFWK_TEST_PASS_FILE_COPY));
}
Jural answered 13/3, 2015 at 19:40 Comment(9)
You can't use C++ reserved words as identifiers in your C code if you intend to feed them to a C++ compiler.Madeira
Why not just #define delete to something else before including the header and #undef delete afterwards?Vanir
@R.. That's probably a very bad idea! Even with the #undef.Archival
@R.. Technically you can't #define a keyword. Most compilers support it as an extension though.Madeira
@TavianBarnes, You legally can if not using the standard library. Unfortunately, with third party headers, it might sometimes end up being the best option under the circumstances.Pannier
@πάνταῥεῖ: If it's your own code and you intend to use it as a C++-accessible interface, then yes, I would agree. But if it's a third-party C library and you're using it as foreign-language code from C++, that might be the simplest solution.Vanir
I'm trying to make this as standard as possible, since my intention is for others to be using it; defining keywords may not end too well, especially since a rename would just be a lot safer!Jural
@R.. From N3242, §17.6.4.3.1, p. 2: "A translation unit shall not #define or #undef names lexically identical to keywords". Admittedly there seems to be some disagreement over what "keyword" means in that context but I always took it to mean that #define delete is illegal.Madeira
@R.. Oh never mind, §17.6.4 "describes restrictions on C++ programs that use the facilities of the C++ standard library", so you're right.Madeira
T
8

"is there anyway to bypass this, or shall I simply rename the function to purge or similar?"

  int(*const delete)(const char* path);
          // ^^^^^^

Yes you should rename it, if the code in question is under your control!
You simply can't use a function pointer named delete in C++ compiled code, because it's a reserved keyword for the language.

You just need to make it different from the keyword. Instead of renaming it to purge, which might be misleading from a semantic level, you can still use something like

int(*const delete_)(const char* path);
              // ^

to get it distinct from the C++ keyword.


About your comments mentioning kind of asymetric/inconsistent naming:
Just use a _ postfix for all of them. As giving an opiniion, that's my preferred style for member variables of structs or classes anyway.

Trishtrisha answered 13/3, 2015 at 19:47 Comment(8)
Yeah, was wondering if anyone had any magic tricks to get round it, but wasn't getting my hopes up! Just wanted an 'expected' function name, 'delete' a file is significantly more common that 'purge' - hey ho!Jural
@Jural You can still use something like delete_ to come over these semantic level concerns.Archival
Good point, hadn't considered that; may look just a little more peculiar than the others, but that ticks all the checkboxes for expectations. Think I'll do that..Jural
what about remove ?Sink
Or delet as homage to creat. :3Suspend
lol :P Might just be me, but remove/unlink just isn't as clear to the final result in comparison to delete...Jural
@Jural "... may look just a little more peculiar than the others ..." Just use a _ postfix for all of them. That's my preferred style for any member variables of structs or classes anyway.Archival
An idea, but I'd rather make it the exception than the rule - I'm careful enough for naming schemes for everything else, it's just purely the semantics of this individual case :)Jural

© 2022 - 2024 — McMap. All rights reserved.