C 库 - 在 C++ 中的使用:重新定义、不同的类型修饰符

C library - use in C++: redefinition, different type modifiers

我最近用纯 C 构建了一个 CSV 库。 头文件如下所示:

  #ifndef CSV_H
  #define CSV_H

    #include "unicode/ustdio.h"
    #include "unicode/uchar.h"
    #include "unicode/ucsdet.h"
    #include "unicode/ustring.h"

    #define T CSV_T
    typedef struct T *T;

    extern T    CSV_new(char *filename);
    extern void CSV_free(T *csv);
    extern int  CSV_length(T csv);
    extern void CSV_print_info(T csv);
    extern UChar **CSV_get_header(T csv);
    extern UChar ***CSV_get_values(T csv);
    extern long CSV_get_num_columns(T csv);
    extern long CSV_get_num_lines(T csv);
    extern char *CSV_get_charset(T csv);

    #undef T
    #endif

结构 CSV_T 的实际定义是在代码文件中完成的,以隐藏实现。我在使用纯 C 的不同项目中经常使用该库,没问题。现在我想在用 C++ 构建的 GUI 应用程序中重新使用代码,但我收到以下错误消息:

Error   C2373   'CSV_T': redefinition; different type modifiers     ... xxx\Projects\LibCSV\LibCSV\csv.h    10  

C++ 处理 typedef 的方式是否与 C 不同?不知何故,...

Here 你的 MCVE 应该是这样的:

typedef struct T *T;

这是一个完整的 one-line 源文件,它重现了问题并且没有依赖项。没有宏,没有 headers,没有不必要的代码。

g++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
main.cpp:1:19: error: conflicting declaration 'typedef struct T* T'
 typedef struct T *T;
                   ^
main.cpp:1:16: note: previous declaration as 'struct T'
 typedef struct T *T;
            ^

它在 C 中工作的原因是 T 还不是结构的名称;您需要 struct 前缀。

在 C++ 中,这是不正确的,因为首先不需要 struct 前缀。一旦你声明 T 是一个 class(令人困惑的是,你在 typedef 本身做了!),你不能只给出一些其他类型(你正在尝试创建与 typedef) 相同的名称。

无论如何,你所做的事情相当奇怪,让 CSV_T 意味着 struct CSV_T*。我建议干脆不要这样做。

如果您只是坚持使用 typedef struct CSV_T CSV_T 那么这将适用于两种语言,但尝试使用相同的名称制作 不同的 类型就不行了去上班了。

C++ 标准的附录 C 说:

7.1.3

Change: A C++ typedef name must be different from any class type name declared in the same scope (except if the typedef is a synonym of the class name with the same name). In C, a typedef name and a struct tag name declared in the same scope can have the same name (because they have different name spaces).

Example:

typedef struct name1 { /.../ } name1; // valid C and C++
struct name { /.../ };
typedef int name; // valid C, invalid C++

Rationale: For ease of use, C++ doesn’t require that a type name be prefixed with the keywords class, struct or union when used in object declarations or type casts.

Example:

 class name { /.../ };
 name i; // i has type class name

Effect on original feature: Deletion of semantically well-defined feature.

Difficulty of converting: Semantic transformation. One of the 2 types has to be renamed.

How widely used: Seldom.